DBA Data[Home] [Help]

PACKAGE BODY: APPS.AME_ENGINE

Source


1 PACKAGE BODY AME_ENGINE as
2 /* $Header: ameeengi.pkb 120.35.12010000.6 2009/01/29 13:35:09 prasashe 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   /*************************************************************************************
410   forward declarations of private functions
411   *************************************************************************************/
412   /******************************** boolean functions *********************************/
413   /*
414     conditionIsSatisfied assumes that itemIndexIn indexes an item ID in engItemIds, and
415     that this item is of the same item class as that of the attribute used by the
416     condition with ID conditionIdIn.
417   */
418   function conditionIsSatisfied(conditionIdIn in integer,
419                                 itemClassIdIn in integer,
420                                 itemIndexIn in integer) return boolean;
421   /********************************* fetch functions **********************************/
422   function fetchAmeApplicationId(fndApplicationIdIn in integer,
423                                  transactionTypeIdIn in varchar2 default null) return integer;
424   /********************************** get functions ***********************************/
425   function getItemIndex(itemClassIdIn in integer,
426                         itemIdIn in varchar2) return integer;
427   function getItemOffset(itemClassIdIn in integer,
428                          itemIdIn in varchar2) return integer;
429   /********************************** sort functions **********************************/
430   /* compareApplicableRules is a subroutine of the sortApplicableRules procedure. */
431   function compareApplicableRules(index1In in integer,
432                                   index2In in integer,
433                                   compareActionTypesIn in boolean) return boolean;
434   function getTestVariantAttValue(attributeIdIn in integer,
435                                  itemClassIdIn  in integer,
436                                  itemIdIn       in varchar2) return number;
437   function isVariant(attributeIdIn in integer) return boolean;
438   /*************************************************************************************
439   forward declarations of private procedures
440   *************************************************************************************/
441   procedure addApproverToTree
442     (approverRecordIn   in            ame_util.approverRecord2
443     ,approverIndexIn    in            integer
444     ,approverLocationIn in            boolean default ame_util.lastAmongEquals);
445   procedure calculateApproverOrderNumbers;
446   procedure compactEngAppLists(compactPrioritiesIn in boolean,
447                                compactActionTypeIdsIn in boolean,
448                                compactParametersIn in boolean);
449   procedure doPerItemRuleEvaluation(itemClassIdIn in integer,
450                                     itemIndexIn in varchar2);
451   procedure doStrictHeaderRuleEvaluation(itemClassIndexIn in integer,
452                                          itemClassIdIn in integer);
453   procedure doWeakHeaderRuleEvaluation(itemClassIndexIn in integer,
454                                        itemClassIdIn in integer);
455   procedure evaluateRules;
456   procedure fetchActiveConditionUsages;
457   procedure fetchApplicableActions;
458   procedure fetchAttributeValues(fetchInactivesIn in boolean);
459   procedure fetchConfigVars;
460   procedure fetchDeletedApprovers;
461   procedure fetchFndApplicationId(applicationIdIn in integer,
462                                   fndApplicationIdOut out nocopy integer,
463                                   transactionTypeIdOut out nocopy varchar2);
464   procedure fetchInsertedApprovers;
465   procedure fetchItemClassData;
466   procedure fetchOldApprovers;
467   procedure fetchRuntimeGroup(groupIdIn in integer);
468   procedure finalizeTree(parentIndexIn          in integer default 1
469                         ,maximumOrderOut       out nocopy integer
470                         ,approvalStatusOut     out nocopy integer
471                         ,rejectedItemsExistOut out nocopy boolean);
472   procedure getLMCondition(ruleIdIn in integer,
473                            parameterOneOut out nocopy varchar2,
474                            parameterTwoOut out nocopy varchar2);
475   procedure insertIntoTransApprovalHistory
476               (transactionIdIn  ame_trans_approval_history.transaction_id%type
477               ,applicationIdIn  ame_trans_approval_history.application_id%type
478               ,orderNumberIn    ame_trans_approval_history.order_number%type
479               ,nameIn           ame_trans_approval_history.name%type
480               ,appCategoryIn    ame_trans_approval_history.approver_category%type
481               ,itemClassIn      ame_trans_approval_history.item_class%type
482               ,itemIdIn         ame_trans_approval_history.item_id%type
483               ,actionTypeIdIn   ame_trans_approval_history.action_type_id%type
484               ,authorityIn      ame_trans_approval_history.authority%type
485               ,statusIn         ame_trans_approval_history.status%type
486               ,grpOrChainIdIn   ame_trans_approval_history.group_or_chain_id%type
487               ,occurrenceIn     ame_trans_approval_history.occurrence%type
488               ,apiInsertionIn   ame_trans_approval_history.api_insertion%type
489               ,memberOrderNumberIn ame_trans_approval_history.member_order_number%type
490               ,notificationIdIn ame_trans_approval_history.notification_id%type
491               ,userCommentsIn   ame_trans_approval_history.user_comments%type
492               ,dateClearedIn    ame_trans_approval_history.date_cleared%type
493               ,historyTypeIn    varchar2);
494   procedure parseForwardingBehaviors(forwardingBehaviorsIn in varchar2);
495   procedure parsePriorityModes(priorityModesIn in varchar2);
496   procedure populateEngStVariables;
497   procedure prepareItemData(approverIndexesIn  in ame_util.idList default ame_util.emptyIdList
498                            ,itemIndexesOut     out nocopy ame_util.idList
499                            ,itemItemClassesOut out nocopy ame_util.stringList
500                            ,itemIdsOut         out nocopy ame_util.stringList
501                            ,itemSourcesOut     out nocopy ame_util.longStringList);
502   procedure preparePerApproverProductions
503            (approverIndexesIn    in ame_util.idList default ame_util.emptyIdList
504            ,itemIndexesIn        in ame_util.idList default ame_util.emptyIdList
505            ,itemSourcesIn        in ame_util.longStringList default ame_util.emptyLongStringList
506            ,prodIndexesOut      out nocopy ame_util.idList
507            ,productionNamesOut  out nocopy ame_util.stringList
508            ,productionValuesOut out nocopy ame_util.stringList);
509   procedure prepareRuleData;
510   procedure processActionType;
511   procedure processAdHocInsertions;
512   procedure processSuppressions;
513   procedure processRelativePriorities;
514   procedure processRepeatedApprovers;
515   procedure processRules(processOnlyProductionsIn in boolean default false);
516   procedure processUnresponsiveApprovers;
517   procedure populateInsertionIndexes(indexIn in integer
518                                     ,insertionOrderIn in integer);
519   procedure repeatSubstitutions;
520   procedure setContext(isTestTransactionIn in boolean,
521                        isLocalTransactionIn in boolean,
522                        fetchConfigVarsIn in boolean,
523                        fetchOldApproversIn in boolean,
524                        fetchInsertionsIn in boolean,
525                        fetchDeletionsIn in boolean,
526                        fetchAttributeValuesIn in boolean,
527                        fetchInactiveAttValuesIn in boolean,
528                        processProductionActionsIn in boolean,
529                        processProductionRulesIn in boolean,
530                        updateCurrentApproverListIn in boolean,
531                        updateOldApproverListIn in boolean,
532                        processPrioritiesIn in boolean,
533                        prepareItemDataIn in boolean,
534                        prepareRuleIdsIn in boolean,
535                        prepareRuleDescsIn in boolean,
536                        prepareApproverTreeIn in boolean default false,
537                        transactionIdIn in varchar2,
538                        ameApplicationIdIn in integer default null,
539                        fndApplicationIdIn in integer default null,
540                        transactionTypeIdIn in varchar2 default null);
541   procedure setInsertedApprovalStatus(currentApproverIndexIn in integer
542                                       ,approvalStatusIn in varchar2);
543 
544   procedure sortApplicableRules(sortByActionTypeIn in boolean);
545   procedure updateOldApproverList;
546   /*************************************************************************************
547   functions
548   *************************************************************************************/
549   /******************************** boolean functions *********************************/
550   function approversMatch(approverRecord1In in ame_util.approverRecord2,
551                           approverRecord2In in ame_util.approverRecord2) return boolean as
552     begin
553       /* The following if statement's conditions are in decreasing order of specificity for efficiency. */
554       if(approverRecord1In.name = approverRecord2In.name and
555          approverRecord1In.occurrence = approverRecord2In.occurrence and
556          approverRecord1In.group_or_chain_id = approverRecord2In.group_or_chain_id and
557          approverRecord1In.action_type_id = approverRecord2In.action_type_id and
558          approverRecord1In.item_id = approverRecord2In.item_id and
559          approverRecord1In.item_class = approverRecord2In.item_class) then
560         return(true);
561       end if;
562       return(false);
563       exception
564         when others then
565           ame_util.runtimeException(packageNameIn => 'ame_engine',
566                                     routineNameIn => 'approversMatch',
567                                     exceptionNumberIn => sqlcode,
568                                     exceptionStringIn => sqlerrm);
569           raise;
570           return(false);
571     end approversMatch;
572   function checkAttributeVariant(attributeIdIn in integer) return varchar2 as
573     begin
574       if (engAttributeNames(attributeIdIn)  = ame_util.jobLevelStartingPointAttribute or
575           engAttributeNames(attributeIdIn)  = ame_util.nonDefStartingPointPosAttr or
576           engAttributeNames(attributeIdIn)  = ame_util.nonDefPosStructureAttr or
577           engAttributeNames(attributeIdIn)  = ame_util.supStartingPointAttribute or
578           engAttributeNames(attributeIdIn)  = ame_util.firstStartingPointAttribute or
579           engAttributeNames(attributeIdIn)  = ame_util.secondStartingPointAttribute ) then
580         return(ame_util.booleanTrue);
581       else
582         return(ame_util.booleanFalse);
583       end if;
584     end;
585   function getVariantAttributeValue(attributeIdIn in integer,
586                                     itemClassIn in varchar2,
587                                     itemIdIn in varchar2) return number as
588     dynamicCursor integer;
589     dynamicQuery ame_util.longestStringType;
590     rowsFound integer;
591     tempAttributeValues1 dbms_sql.varchar2_table;
592     begin
593       if engIsTestTransaction then
594         if checkAttributeVariant(attributeIdIn) = ame_util.booleanTrue then
595           return (getTestVariantAttValue(attributeIdIn => attributeIdIn
596                                         ,itemClassIdIn => getItemClassId(itemClassNameIn => itemClassIn)
597                                         ,itemIdIn      => itemIdIn));
598         else
599           return(engAttributeValues1(engAttributeValueIndexes(attributeIdIn)));
600         end if;
601       end if;
602       /* fetch the value for real transactions using the dynamic query */
603       if(engAttributeVariant.exists(attributeIdIn))then
604         dynamicQuery := ame_util.removeReturns(stringIn => engAttributeQueries(attributeIdIn),
605                                                replaceWithSpaces => true);
606         dynamicCursor := dbms_sql.open_cursor;
607         dbms_sql.parse(dynamicCursor,
608                        dynamicQuery,
609                        dbms_sql.native);
610         if(instrb(dynamicQuery, ame_util.transactionIdPlaceholder) > 0) then
611           dbms_sql.bind_variable(dynamicCursor,
612                                  ame_util.transactionIdPlaceholder,
613                                  engTransactionId,
614                                  50); /* ame_temp_transactions.transaction_id%length doesn't work here. */
615         end if;
616         if(instrb(dynamicQuery, ame_util2.itemClassPlaceHolder) > 0) then
617           dbms_sql.bind_variable(dynamicCursor,
618                                  ame_util2.itemClassPlaceHolder,
619                                  itemClassIn,
620                                  50); /* ame_temp_transactions.transaction_id%length doesn't work here. */
621         end if;
622         if(instrb(dynamicQuery, ame_util2.itemIdPlaceHolder) > 0) then
623           dbms_sql.bind_variable(dynamicCursor,
624                                  ame_util2.itemIdPlaceHolder,
625                                  itemIdIn,
626                                  50); /* ame_temp_transactions.transaction_id%length doesn't work here. */
627         end if;
628         dbms_sql.define_array(dynamicCursor,
629                               1,
630                               tempAttributeValues1,
631                               ame_util.attributeValueTypeLength,
632                               1);
633         rowsFound := dbms_sql.execute(dynamicCursor);
634         loop
635           rowsFound := dbms_sql.fetch_rows(dynamicCursor);
636           dbms_sql.column_value(dynamicCursor,
637                                 1,
638                                 tempAttributeValues1);
639           exit when rowsFound < 2;
640         end loop;
641         dbms_sql.close_cursor(dynamicCursor);
642         return(tempAttributeValues1(1));
643       else
644       /* this is not a variant attribute value would have fetched already in
645          fetchAttributeValues return the same */
646         return(engAttributeValues1(engAttributeValueIndexes(attributeIdIn)));
647       end if;
648       exception
649         when others then
650           ame_util.runtimeException(packageNameIn => 'ame_engine',
651                                     routineNameIn => 'getVariantAttributeValue',
652                                     exceptionNumberIn => sqlcode,
653                                     exceptionStringIn => sqlerrm);
654           raise;
655           return null;
656     end getVariantAttributeValue;
657 /*  function getVariantAttributeValue2(attributeIdIn in integer,
658                                      itemClassIn in varchar2,
659                                      itemIdIn in varchar2) return number as
660     begin
661       return(getVariantAttributeValue(attributeIdIn => attributeIdIn,
662                                       itemClassIn => itemClassIn,
663                                       itemIdIn => itemIdIn));
664       exception
665         when others then
666           ame_util.runtimeException(packageNameIn => 'ame_engine',
667                                     routineNameIn => 'getVariantAttributeValue2',
668                                     exceptionNumberIn => sqlcode,
669                                     exceptionStringIn => sqlerrm);
670           raise;
671           return null;
672     end getVariantAttributeValue2;*/
673   function conditionIsSatisfied(conditionIdIn in integer,
674                                 itemClassIdIn in integer,
675                                 itemIndexIn in integer) return boolean as
676     attributeId integer;
677     attributeNumberValue number;
678     attributeType ame_attributes.attribute_type%type;
679     attributeTypeException exception;
680     attributeValue1 ame_util.attributeValueType;
681     attributeValue2 ame_util.attributeValueType;
682     attributeValue3 ame_util.attributeValueType;
683     attributeValueDate date;
684     errorCode integer;
685     errorMessage ame_util.longestStringType;
686     headerLevelCondition boolean;
687     includeLowerLimit ame_conditions.include_lower_limit%type;
688     includeUpperLimit ame_conditions.include_upper_limit%type;
689     parameterOne ame_conditions.parameter_one%type;
690     parameterOneDate date;
691     parameterOneNumber number;
692     parameterThree ame_conditions.parameter_three%type;
693     parameterTwo ame_conditions.parameter_two%type;
694     parameterTwoDate date;
695     parameterTwoNumber number;
696     begin
697       /* Check whether the condition is on a header-level attribute. */
698       if(engItemClassNames(engItemClassIndexes(engAttributeItemClassIds(engACAttributeIds(conditionIdIn)))) =
699            ame_util.headerItemClassName) then
700         headerLevelCondition := true;
701       else
702         headerLevelCondition := false;
703       end if;
704       attributeId := engACAttributeIds(conditionIdIn);
705       /* Check for a cached value, for conditions on header-level attributes. */
706       if (headerLevelCondition and
707            not engIsTestTransaction and
708            not engAttributeVariant.exists(attributeId) and
709            engHeaderConditionValues.exists(conditionIdIn)) then
710         /* The value is cached. */
711         if(engHeaderConditionValues(conditionIdIn) = ame_util.booleanTrue) then
712           return(true);
713         end if;
714         return(false);
715       end if;
716       /* The value must be calculated. */
717       attributeType := engAttributeTypes(attributeId);
718       if(attributeType <> ame_util.stringAttributeType) then
719         includeLowerLimit := engACIncludeLowerLimits(conditionIdIn);
720         includeUpperLimit := engACIncludeUpperLimits(conditionIdIn);
721         parameterOne := engACParameterOnes(conditionIdIn);
722         parameterTwo := engACParameterTwos(conditionIdIn);
723         parameterThree := engACParameterThrees(conditionIdIn);
724       end if;
725       if(headerLevelCondition) then
726         if isVariant(attributeId) then
727           attributeValue1 :=  getVariantAttributeValue
728                                  (attributeIdIn => attributeId,
729                                   itemClassIn   => getItemClassName(itemClassIdIn => itemClassIdIn),
730                                   itemIdIn      => engItemIds(itemIndexIn));
731         else
732           getHeaderAttValues1(attributeIdIn => attributeId,
733                               attributeValue1Out => attributeValue1,
734                               attributeValue2Out => attributeValue2,
735                               attributeValue3Out => attributeValue3);
736         end if;
737       else
738         getItemAttValues3(attributeIdIn => attributeId,
739                           itemIndexIn => itemIndexIn,
740                           attributeValue1Out => attributeValue1,
741                           attributeValue2Out => attributeValue2,
742                           attributeValue3Out => attributeValue3);
743       end if;
744       /* numbers and currencies */
745       if(attributeType = ame_util.numberAttributeType or
746          attributeType = ame_util.currencyAttributeType) then
747         /* First handle the case of a null value. */
748         if(attributeValue1 is null) then
749           if(parameterOne is null and
750              parameterTwo is null) then
751             if(headerLevelCondition) then
752               engHeaderConditionValues(conditionIdIn) := ame_util.booleanTrue;
753             end if;
754             return(true);
755           else
756             if(headerLevelCondition) then
757               engHeaderConditionValues(conditionIdIn) := ame_util.booleanFalse;
758             end if;
759             return(false);
760           end if;
761         end if;
762         /* Now handle the other cases. */
763         if(attributeType = ame_util.currencyAttributeType and
764         /* Issue 6 of the Bug list bug (4094080) */
765         /* modified form parameterThree <> attributeValue3 to */
766         /* parameterThree <> attributeValue2 */
767            parameterThree <> attributeValue2) then
768           attributeNumberValue :=
769             ame_util.convertCurrency(fromCurrencyCodeIn => attributeValue2,
770                                      toCurrencyCodeIn => parameterThree,
771                                      conversionTypeIn => attributeValue3,
772                                      amountIn => fnd_number.canonical_to_number(canonical => attributeValue1),
773                                      dateIn => engEffectiveRuleDate,
774                                      applicationIdIn => engAmeApplicationId);
775         else
776           attributeNumberValue := fnd_number.canonical_to_number(canonical => attributeValue1);
777         end if;
778         parameterOneNumber := fnd_number.canonical_to_number(canonical => parameterOne);
779         parameterTwoNumber := fnd_number.canonical_to_number(canonical => parameterTwo);
780         if(includeLowerLimit = ame_util.booleanTrue and
781            attributeNumberValue = parameterOneNumber) then
782           if(headerLevelCondition) then
783             engHeaderConditionValues(conditionIdIn) := ame_util.booleanTrue;
784           end if;
785           return(true);
786         end if;
787         if(includeUpperLimit = ame_util.booleanTrue and
788            attributeNumberValue = parameterTwoNumber) then
789           if(headerLevelCondition) then
790             engHeaderConditionValues(conditionIdIn) := ame_util.booleanTrue;
791           end if;
792           return(true);
793         end if;
794         if((parameterOneNumber is null and attributeNumberValue < parameterTwoNumber) or
795            (parameterOneNumber < attributeNumberValue and parameterTwoNumber is null) or
796            (parameterOneNumber < attributeNumberValue and attributeNumberValue < parameterTwoNumber)) then
797           if(headerLevelCondition) then
798             engHeaderConditionValues(conditionIdIn) := ame_util.booleanTrue;
799           end if;
800           return(true);
801         end if;
802       /* dates */
803       elsif(attributeType = ame_util.dateAttributeType) then
804         attributeValueDate := ame_util.versionStringToDate(stringDateIn => attributeValue1);
805         parameterOneDate := ame_util.versionStringToDate(stringDateIn => parameterOne);
806         parameterTwoDate := ame_util.versionStringToDate(stringDateIn => parameterTwo);
807         /* First handle the case of a null value. */
808         if(attributeValue1 is null) then
809           if(parameterOne is null and
810              parameterTwo is null) then
811             if(headerLevelCondition) then
812               engHeaderConditionValues(conditionIdIn) := ame_util.booleanTrue;
813             end if;
814             return(true);
815           else
816             if(headerLevelCondition) then
817               engHeaderConditionValues(conditionIdIn) := ame_util.booleanFalse;
818             end if;
819             return(false);
820           end if;
821         end if;
822         /* Now handle the other cases. */
823         if(includeLowerLimit = ame_util.booleanTrue and
824            attributeValueDate = parameterOneDate) then
825           if(headerLevelCondition) then
826             engHeaderConditionValues(conditionIdIn) := ame_util.booleanTrue;
827           end if;
828           return(true);
829         end if;
830         if(includeUpperLimit = ame_util.booleanTrue and
831            attributeValueDate = parameterTwoDate) then
832           if(headerLevelCondition) then
833             engHeaderConditionValues(conditionIdIn) := ame_util.booleanTrue;
834           end if;
835           return(true);
836         end if;
837         if((parameterOneDate is null and attributeValueDate < parameterTwoDate) or
838            (parameterOneDate < attributeValueDate and parameterTwoDate is null) or
839            (parameterOneDate < attributeValueDate and attributeValueDate < parameterTwoDate)) then
840           if(headerLevelCondition) then
841             engHeaderConditionValues(conditionIdIn) := ame_util.booleanTrue;
842           end if;
843           return(true);
844         end if;
845       /* booleans */
846       elsif(attributeType = ame_util.booleanAttributeType) then
847         if((attributeValue1 is null and
848             parameterOne is null) or
849            attributeValue1 = parameterOne) then
850           if(headerLevelCondition) then
851             engHeaderConditionValues(conditionIdIn) := ame_util.booleanTrue;
852           end if;
853           return(true); /* If both pseudo-booleans are null, the condition applies. */
854         end if;
855         return(false);
856       /* strings */
857       elsif(attributeType = ame_util.stringAttributeType) then
858         /* Note that if the attribute value and a string value are both null, the condition applies. */
859         for stringValueIndex in
860           engACStringValueFirstIndexes(conditionIdIn) ..
861           (engACStringValueFirstIndexes(conditionIdIn) + engACStringValueCounts(conditionIdIn) - 1) loop
862           if((attributeValue1 is null and engACStringValues(stringValueIndex) is null) or
863              attributeValue1 = engACStringValues(stringValueIndex)) then
864             if(headerLevelCondition) then
865               engHeaderConditionValues(conditionIdIn) := ame_util.booleanTrue;
866             end if;
867             return(true);
868           end if;
869         end loop;
870       else
871         raise attributeTypeException;
872       end if;
873       /* The condition is not satisfied. */
874       if(headerLevelCondition) then
875         engHeaderConditionValues(conditionIdIn) := ame_util.booleanFalse;
876       end if;
877       return(false);
878       exception
879         when attributeTypeException then
880           errorCode := -20001;
881           errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
882                                               messageNameIn => 'AME_400113_ENG_ATTR_UNREG_TYPE');
883           ame_util.runtimeException(packageNameIn => 'ame_engine',
884                                     routineNameIn => 'conditionIsSatisfied',
885                                     exceptionNumberIn => errorCode,
886                                     exceptionStringIn => errorMessage);
887           raise_application_error(errorCode,
888                                   errorMessage);
889           return(null);
890         when others then
891           ame_util.runtimeException(packageNameIn => 'ame_engine',
892                                     routineNameIn => 'conditionIsSatisfied',
893                                     exceptionNumberIn => sqlcode,
894                                     exceptionStringIn => sqlerrm);
895           raise;
896           return(null);
897     end conditionIsSatisfied;
898   function evalPrioritiesPerItem return boolean as
899     begin
900       return(engEvalPrioritiesPerItem);
901       exception
902         when others then
903           ame_util.runtimeException(packageNameIn => 'ame_engine',
904                                     routineNameIn => 'evalPrioritiesPerItem',
905                                     exceptionNumberIn => sqlcode,
906                                     exceptionStringIn => sqlerrm);
907           raise;
908           return(null);
909     end evalPrioritiesPerItem;
910   function insertionExists(orderTypeIn in varchar2,
911                            parameterIn in varchar2) return boolean as
912     begin
913       for i in 1 .. engInsertionOrderTypeList.count loop
914         if(engInsertionOrderTypeList(i) = orderTypeIn and
915            engInsertionParameterList(i) = parameterIn) then
916           return(true);
917         end if;
918       end loop;
919       return(false);
920       exception
921         when others then
922           ame_util.runtimeException(packageNameIn => 'ame_engine',
923                                     routineNameIn => 'insertionExists',
924                                     exceptionNumberIn => sqlcode,
925                                     exceptionStringIn => sqlerrm);
926           raise;
927           return(null);
928     end insertionExists;
929   function isLocalTransaction return boolean as
930     begin
931       return(engIsLocalTransaction);
932       exception
933         when others then
934           ame_util.runtimeException(packageNameIn => 'ame_engine',
935                                     routineNameIn => 'isLocalTransaction',
936                                     exceptionNumberIn => sqlcode,
937                                     exceptionStringIn => sqlerrm);
938           raise;
939           return(null);
940     end isLocalTransaction;
941   function isStaticAttUsage(attributeIdIn in integer) return boolean as
942     begin
943       if(engAttributeIsStatics(attributeIdIn) = ame_util.booleanTrue) then
944         return(true);
945       end if;
946       return(false);
947       exception
948         when others then
949           ame_util.runtimeException(packageNameIn => 'ame_engine',
950                                     routineNameIn => 'isStaticAttUsage',
951                                     exceptionNumberIn => sqlcode,
952                                     exceptionStringIn => sqlerrm);
953           raise;
954           return(false);
955     end isStaticAttUsage;
956   function isTestTransaction return boolean as
957     begin
958       return(engIsTestTransaction);
959       exception
960         when others then
961           ame_util.runtimeException(packageNameIn => 'ame_engine',
962                                     routineNameIn => 'isTestTransaction',
963                                     exceptionNumberIn => sqlcode,
964                                     exceptionStringIn => sqlerrm);
965           raise;
966           return(null);
967     end isTestTransaction;
968   function isVariant(attributeIdIn in integer) return boolean as
969   begin
970     if checkAttributeVariant(attributeIdIn) = ame_util.booleanTrue then
971       if engIsTestTransaction then
972         return true;
973       elsif engAttributeVariant.exists(attributeIdIn) then
974         return true;
975       end if;
976     end if;
977     return false;
978     exception
979       when others then
980         ame_util.runtimeException(packageNameIn => 'ame_engine',
981                                   routineNameIn => 'isVariant',
982                                   exceptionNumberIn => sqlcode,
983                                   exceptionStringIn => sqlerrm);
984         raise;
985         return(null);
986   end isVariant;
987   function processPriorities return boolean as
988     begin
989       return(engProcessPriorities);
990       exception
991         when others then
992           ame_util.runtimeException(packageNameIn => 'ame_engine',
993                                     routineNameIn => 'processPriorities',
994                                     exceptionNumberIn => sqlcode,
995                                     exceptionStringIn => sqlerrm);
996           raise;
997           return(null);
998     end processPriorities;
999   function processProductionActions return boolean as
1000     begin
1001       return(engProcessProductionActions);
1002       exception
1003         when others then
1004           ame_util.runtimeException(packageNameIn => 'ame_engine',
1005                                     routineNameIn => 'processProductionActions',
1006                                     exceptionNumberIn => sqlcode,
1007                                     exceptionStringIn => sqlerrm);
1008           raise;
1009           return(null);
1010     end processProductionActions;
1011   function processProductionRules return boolean as
1012     begin
1013       return(engProcessProductionRules);
1014       exception
1015         when others then
1016           ame_util.runtimeException(packageNameIn => 'ame_engine',
1017                                     routineNameIn => 'processProductionRules',
1018                                     exceptionNumberIn => sqlcode,
1019                                     exceptionStringIn => sqlerrm);
1020           raise;
1021           return(null);
1022     end processProductionRules;
1023   /********************************* fetch functions **********************************/
1024   function fetchAmeApplicationId(fndApplicationIdIn in integer,
1025                                  transactionTypeIdIn in varchar2 default null) return integer as
1026     ameApplicationId integer;
1027     begin
1028       select application_id
1029         into ameApplicationId
1030         from ame_calling_apps
1031         where
1032           fnd_application_id = fndApplicationIdIn and
1033           ((transactionTypeIdIn is null and transaction_type_id is null) or
1034            (transaction_type_id = transactionTypeIdIn)) and
1035           /* Don't use engEffectiveRuleDate here. */
1036           sysdate between
1037             start_date and
1038             nvl(end_date - ame_util.oneSecond, sysdate) and
1039           rownum < 2; /* Avoids second fetch otherwise required by ANSI standard to check for too many rows. */
1040       return(ameApplicationId);
1041       exception
1042         when others then
1043           ame_util.runtimeException(packageNameIn => 'ame_engine',
1044                                     routineNameIn => 'fetchAmeApplicationId',
1045                                     exceptionNumberIn => sqlcode,
1046                                     exceptionStringIn => sqlerrm);
1047           raise;
1048           return(null);
1049     end fetchAmeApplicationId;
1050   /********************************** get functions ***********************************/
1051   function getActionTypeChainOrderMode(actionTypeIdIn in integer) return varchar2 as
1052     begin
1053       return(engActionTypeChainOrderModes(actionTypeIdIn));
1054       exception
1055         when others then
1056           ame_util.runtimeException(packageNameIn => 'ame_engine',
1057                                     routineNameIn => 'getActionTypeChainOrderMode',
1058                                     exceptionNumberIn => sqlcode,
1059                                     exceptionStringIn => sqlerrm);
1060           raise;
1061           return(null);
1062     end getActionTypeChainOrderMode;
1063   function getActionTypeId(actionTypeNameIn in varchar2) return integer as
1064     tempIndex integer;
1065     begin
1066       tempIndex := engActionTypeNames.first;
1067       while(tempIndex is not null) loop
1068         if(engActionTypeNames(tempIndex) = actionTypeNameIn) then
1069           return(tempIndex);
1070         end if;
1071         tempIndex := engActionTypeNames.next(tempIndex);
1072       end loop;
1073       return(null);
1074       exception
1075         when others then
1076           ame_util.runtimeException(packageNameIn => 'ame_engine',
1077                                     routineNameIn => 'getActionTypeId',
1078                                     exceptionNumberIn => sqlcode,
1079                                     exceptionStringIn => sqlerrm);
1080           raise;
1081           return(null);
1082     end getActionTypeId;
1083   function getActionTypeName(actionTypeIdIn in integer) return varchar2 as
1084     begin
1085       return(engActionTypeNames(actionTypeIdIn));
1086       exception
1087         when others then
1088           ame_util.runtimeException(packageNameIn => 'ame_engine',
1089                                     routineNameIn => 'getActionTypeName',
1090                                     exceptionNumberIn => sqlcode,
1091                                     exceptionStringIn => sqlerrm);
1092           raise;
1093           return(null);
1094     end getActionTypeName;
1095   function getActionTypeOrderNumber(actionTypeIdIn in integer) return integer as
1096     begin
1097       return(engActionTypeOrderNumbers(actionTypeIdIn));
1098       exception
1099         when others then
1100           ame_util.runtimeException(packageNameIn => 'ame_engine',
1101                                     routineNameIn => 'getActionTypeOrderNumber',
1102                                     exceptionNumberIn => sqlcode,
1103                                     exceptionStringIn => sqlerrm);
1104           raise;
1105           return(null);
1106     end getActionTypeOrderNumber;
1107   function getActionTypePackageName(actionTypeIdIn in integer) return varchar2 as
1108     begin
1109       return(engActionTypePackageNames(actionTypeIdIn));
1110       exception
1111         when others then
1112           ame_util.runtimeException(packageNameIn => 'ame_engine',
1113                                     routineNameIn => 'getActionTypePackageName',
1114                                     exceptionNumberIn => sqlcode,
1115                                     exceptionStringIn => sqlerrm);
1116           raise;
1117           return(null);
1118     end getActionTypePackageName;
1119   function getActionTypeUsage(actionTypeIdIn in integer) return integer as
1120     begin /* getActionTypeUsage returns the rule type that uses the input action type. */
1121       return(engActionTypeUsages(actionTypeIdIn));
1122       exception
1123         when others then
1124           ame_util.runtimeException(packageNameIn => 'ame_engine',
1125                                     routineNameIn => 'getActionTypeUsage',
1126                                     exceptionNumberIn => sqlcode,
1127                                     exceptionStringIn => sqlerrm);
1128           raise;
1129           return(null);
1130     end getActionTypeUsage;
1131   function getActionTypeVotingRegime(actionTypeIdIn in integer) return varchar2 as
1132     begin
1133       if(actionTypeIdIn = ame_util.nullInsertionActionTypeId or actionTypeIdIn = -2 ) then
1134         return(null);
1135       end if;
1136       return(engActionTypeVotingRegimes(actionTypeIdIn));
1137       exception
1138         when others then
1139           ame_util.runtimeException(packageNameIn => 'ame_engine',
1140                                     routineNameIn => 'getActionTypeVotingRegime',
1141                                     exceptionNumberIn => sqlcode,
1142                                     exceptionStringIn => sqlerrm);
1143           raise;
1144           return(null);
1145     end getActionTypeVotingRegime;
1146   function getAmeApplicationId return integer as
1147     begin
1148       return(engAmeApplicationId);
1149       exception
1150         when others then
1151           ame_util.runtimeException(packageNameIn => 'ame_engine',
1152                                     routineNameIn => 'getAmeApplicationId',
1153                                     exceptionNumberIn => sqlcode,
1154                                     exceptionStringIn => sqlerrm);
1155           raise;
1156           return(null);
1157     end getAmeApplicationId;
1158   function getApprovalProcessCompleteYN return varchar2 as
1159     begin
1160       return(engStApprovalProcessCompleteYN);
1161       exception
1162         when others then
1163           ame_util.runtimeException(packageNameIn => 'ame_engine',
1164                                     routineNameIn => 'getApprovalProcessCompleteYN',
1165                                     exceptionNumberIn => sqlcode,
1166                                     exceptionStringIn => sqlerrm);
1167           raise;
1168           return(null);
1169     end getApprovalProcessCompleteYN;
1170   function getAttributeIdByName(attributeNameIn in varchar2) return integer as
1171     errorCode integer;
1172     errorMessage ame_util.longestStringType;
1173     notFoundException exception;
1174     tempIndex integer;
1175     begin
1176       tempIndex := engAttributeNames.first;
1177       loop
1178         if(tempIndex is null) then
1179           raise notFoundException;
1180         end if;
1181         if(engAttributeNames(tempIndex) = attributeNameIn) then
1182           return(tempIndex);
1183         end if;
1184         tempIndex := engAttributeNames.next(tempIndex);
1185       end loop;
1186       exception
1187         when notFoundException then
1188           errorCode := -20001;
1189           errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
1190                                               messageNameIn   => 'AME_400680_NO_ID_FOR_ATTR',
1191                                               tokenNameOneIn  => 'ATTRIBUTE_NAME',
1192                                               tokenValueOneIn => attributeNameIn);
1193           ame_util.runtimeException(packageNameIn => 'ame_engine',
1194                                     routineNameIn => 'getAttributeIdByName',
1195                                     exceptionNumberIn => errorCode,
1196                                     exceptionStringIn => errorMessage);
1197           raise_application_error(errorCode, errorMessage);
1198           return(null);
1199         when others then
1200           ame_util.runtimeException(packageNameIn => 'ame_engine',
1201                                     routineNameIn => 'getAttributeIdByName',
1202                                     exceptionNumberIn => sqlcode,
1203                                     exceptionStringIn => attributeNameIn || ':  ' || sqlerrm);
1204           raise;
1205           return(null);
1206     end getAttributeIdByName;
1207   function getAttributeName(attributeIdIn in integer) return varchar2 as
1208     begin
1209       return(engAttributeNames(attributeIdIn));
1210       exception
1211         when others then
1212           ame_util.runtimeException(packageNameIn => 'ame_engine',
1213                                     routineNameIn => 'getAttributeName',
1214                                     exceptionNumberIn => sqlcode,
1215                                     exceptionStringIn => sqlerrm);
1216           raise;
1217           return(null);
1218     end getAttributeName;
1219   function getAttributeType(attributeIdIn in integer) return varchar2 as
1220     begin
1221       return(engAttributeTypes(attributeIdIn));
1222       exception
1223         when others then
1224           ame_util.runtimeException(packageNameIn => 'ame_engine',
1225                                     routineNameIn => 'getAttributeType',
1226                                     exceptionNumberIn => sqlcode,
1227                                     exceptionStringIn => sqlerrm);
1228           raise;
1229           return(null);
1230     end getAttributeType;
1231   function getConfigVarValue(configVarNameIn in varchar2) return varchar2 as
1232     errorCode integer;
1233     errorMessage ame_util.longestStringType;
1234     noValueException exception;
1235     begin
1236       for i in 1 .. engConfigVarNames.count loop
1237         if(engConfigVarNames(i) = configVarNameIn) then
1238           return(engConfigVarValues(i));
1239         end if;
1240       end loop;
1241       raise noValueException;
1242       exception
1243         when noValueException then
1244           errorCode := -20001;
1245           errorMessage := ame_util.getMessage(applicationShortNameIn => 'PER',
1246                                               messageNameIn => 'AME_400114_ENG_INV_CON_VAR',
1247                                               tokenNameOneIn => 'CONFIG_VAR',
1248                                               tokenValueOneIn => configVarNameIn);
1249           ame_util.runtimeException(packageNameIn => 'ame_engine',
1250                                     routineNameIn => 'getConfigVarValue',
1251                                     exceptionNumberIn => errorCode,
1252                                     exceptionStringIn => errorMessage);
1253           raise_application_error(errorCode,
1254                                   errorMessage);
1255         when others then
1256           ame_util.runtimeException(packageNameIn => 'ame_engine',
1257                                     routineNameIn => 'getConfigVarValue',
1258                                     exceptionNumberIn => sqlcode,
1259                                     exceptionStringIn => sqlerrm);
1260           raise;
1261           return(null);
1262     end getConfigVarValue;
1263   function getEffectiveRuleDate return date as
1264     begin
1265       return(engEffectiveRuleDate);
1266       exception
1267         when others then
1268           ame_util.runtimeException(packageNameIn => 'ame_engine',
1269                                     routineNameIn => 'getEffectiveRuleDate',
1270                                     exceptionNumberIn => sqlcode,
1271                                     exceptionStringIn => sqlerrm);
1272           raise;
1273           return(null);
1274     end getEffectiveRuleDate;
1275   function getFndApplicationId return integer as
1276     begin
1277       return(engFndApplicationId);
1278       exception
1279         when others then
1280           ame_util.runtimeException(packageNameIn => 'ame_engine',
1281                                     routineNameIn => 'getFndApplicationId',
1282                                     exceptionNumberIn => sqlcode,
1283                                     exceptionStringIn => sqlerrm);
1284           raise;
1285           return(null);
1286     end getFndApplicationId;
1287   function getForwardingBehavior(forwarderTypeIn in varchar2,
1288                                  forwardeeTypeIn in varchar2,
1289                                  approvalStatusIn in varchar2) return varchar2 as
1290     errorCode integer;
1291     errorMessage ame_util.longestStringType;
1292     badArgsException exception;
1293     begin
1294       if(forwarderTypeIn = ame_util.chainOfAuthorityForwarder) then
1295         if(forwardeeTypeIn = ame_util.previousSameChainForwardee) then
1296           if(approvalStatusIn = ame_util.forwardStatus) then
1297             return(engForwardingBehaviors(1));
1298           elsif(approvalStatusIn = ame_util.approveAndForwardStatus) then
1299             return(engForwardingBehaviors(2));
1300           end if;
1301         elsif(forwardeeTypeIn = ame_util.subordSameHierarchyForwardee) then
1302           if(approvalStatusIn = ame_util.forwardStatus) then
1303             return(engForwardingBehaviors(3));
1304           elsif(approvalStatusIn = ame_util.approveAndForwardStatus) then
1305             return(engForwardingBehaviors(4));
1306           end if;
1307         elsif(forwardeeTypeIn = ame_util.alreadyInListForwardee) then
1308           if(approvalStatusIn = ame_util.forwardStatus) then
1309             return(engForwardingBehaviors(5));
1310           elsif(approvalStatusIn = ame_util.approveAndForwardStatus) then
1311             return(engForwardingBehaviors(6));
1312           end if;
1313         end if;
1314       elsif(forwarderTypeIn = ame_util.adHocForwarder) then
1315         if(forwardeeTypein = ame_util.alreadyInListForwardee) then
1316           if(approvalStatusIn = ame_util.forwardStatus) then
1317             return(engForwardingBehaviors(7));
1318           elsif(approvalStatusIn = ame_util.approveAndForwardStatus) then
1319             return(engForwardingBehaviors(8));
1320           end if;
1321         end if;
1322       end if;
1323       raise badArgsException;
1324       exception
1325         when badArgsException then
1326           errorCode := -20001;
1327           errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
1328                                               messageNameIn => 'AME_400115_ENG_INV_VAL_ARG');
1329           ame_util.runtimeException(packageNameIn => 'ame_engine',
1330                                     routineNameIn => 'getForwardingBehavior',
1331                                     exceptionNumberIn => errorCode,
1332                                     exceptionStringIn => errorMessage);
1333           raise_application_error(errorCode,
1334                                   errorMessage);
1335           return(null);
1336         when others then
1337           ame_util.runtimeException(packageNameIn => 'ame_engine',
1338                                     routineNameIn => 'getForwardingBehavior',
1339                                     exceptionNumberIn => sqlcode,
1340                                     exceptionStringIn => sqlerrm);
1341           raise;
1342           return(null);
1343     end getForwardingBehavior;
1344   function getHandlerActionTypeId return integer as
1345     begin
1346       return(engAppActionTypeIds(engAppHandlerFirstIndex));
1347       exception
1348         when others then
1349           ame_util.runtimeException(packageNameIn => 'ame_engine',
1350                                     routineNameIn => 'getHandlerActionTypeId',
1351                                     exceptionNumberIn => sqlcode,
1352                                     exceptionStringIn => sqlerrm);
1353           raise;
1354           return(null);
1355     end getHandlerActionTypeId;
1356   function getHandlerActionTypeOrderNum return integer as
1357     begin
1358       return(engActionTypeOrderNumbers(engAppActionTypeIds(engAppHandlerFirstIndex)));
1359       exception
1360         when others then
1361           ame_util.runtimeException(packageNameIn => 'ame_engine',
1362                                     routineNameIn => 'getHandlerActionTypeOrderNum',
1363                                     exceptionNumberIn => sqlcode,
1364                                     exceptionStringIn => sqlerrm);
1365           raise;
1366           return(null);
1367     end getHandlerActionTypeOrderNum;
1368   function getHandlerApprovalStatus(approverIn in ame_util.approverRecord2) return varchar2 as
1369     begin
1370       for i in 1 .. engOldApproverList.count loop
1371         if(approversMatch(approverRecord1In => approverIn,
1372                           approverRecord2In => engOldApproverList(i))) then
1373           return(engOldApproverList(i).approval_status);
1374         end if;
1375       end loop;
1376       return(null);
1377       exception
1378         when others then
1379           ame_util.runtimeException(packageNameIn => 'ame_engine',
1380                                     routineNameIn => 'getHandlerApprovalStatus',
1381                                     exceptionNumberIn => sqlcode,
1382                                     exceptionStringIn => sqlerrm);
1383           raise;
1384           return(null);
1385     end getHandlerApprovalStatus;
1386   function getHandlerAuthority return varchar2 as
1387     errorCode integer;
1388     errorMessage ame_util.longestStringType;
1389     badRuleTypeException exception;
1390     ruleType integer;
1391     begin
1392       ruleType := getHandlerRuleType;
1393       if(ruleType = ame_util.preListGroupRuleType) then
1394         return(ame_util.preApprover);
1395       elsif(ruleType = ame_util.postListGroupRuleType) then
1396         return(ame_util.postApprover);
1397       elsif(ruleType = ame_util.authorityRuleType) then
1398         return(ame_util.authorityApprover);
1399       else
1400         raise badRuleTypeException;
1401       end if;
1402       exception
1403         when badRuleTypeException then
1404           errorCode := -20001;
1405           errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
1406                                               messageNameIn => 'AME_400681_INV_HANDLER_RUL_TYP');
1407           ame_util.runtimeException(packageNameIn => 'ame_engine',
1408                                     routineNameIn => 'getHandlerAuthority',
1409                                     exceptionNumberIn => errorCode,
1410                                     exceptionStringIn => errorMessage);
1411           raise_application_error(errorCode,
1412                                   errorMessage);
1413           return(null);
1414         when others then
1415           ame_util.runtimeException(packageNameIn => 'ame_engine',
1416                                     routineNameIn => 'getHandlerAuthority',
1417                                     exceptionNumberIn => sqlcode,
1418                                     exceptionStringIn => sqlerrm);
1419           raise;
1420           return(null);
1421     end getHandlerAuthority;
1422   function getHandlerItemClassId return integer as
1423     begin
1424       return(engAppRuleItemClassIds(engAppHandlerFirstIndex));
1425       exception
1426         when others then
1427           ame_util.runtimeException(packageNameIn => 'ame_engine',
1428                                     routineNameIn => 'getHandlerItemClassId',
1429                                     exceptionNumberIn => sqlcode,
1430                                     exceptionStringIn => sqlerrm);
1431           raise;
1432           return(null);
1433     end getHandlerItemClassId;
1434   function getHandlerItemClassName return varchar2 as
1435     begin
1436       return(getItemClassName(itemClassIdIn => engAppRuleItemClassIds(engAppHandlerFirstIndex)));
1437       exception
1438         when others then
1439           ame_util.runtimeException(packageNameIn => 'ame_engine',
1440                                     routineNameIn => 'getHandlerItemClassName',
1441                                     exceptionNumberIn => sqlcode,
1442                                     exceptionStringIn => sqlerrm);
1443           raise;
1444           return(null);
1445     end getHandlerItemClassName;
1446   function getHandlerItemClassOrderNumber return integer as
1447     begin
1448       return(engItemClassOrderNumbers(engItemClassIndexes(engAppRuleItemClassIds(engAppHandlerFirstIndex))));
1449       exception
1450         when others then
1451           ame_util.runtimeException(packageNameIn => 'ame_engine',
1452                                     routineNameIn => 'getHandlerItemClassOrderNumber',
1453                                     exceptionNumberIn => sqlcode,
1454                                     exceptionStringIn => sqlerrm);
1455           raise;
1456           return(null);
1457     end getHandlerItemClassOrderNumber;
1458   function getHandlerItemId return varchar2 as
1459     begin
1460       return(engAppAppItemIds(engAppHandlerFirstIndex));
1461       exception
1462         when others then
1463           ame_util.runtimeException(packageNameIn => 'ame_engine',
1464                                     routineNameIn => 'getHandlerItemId',
1465                                     exceptionNumberIn => sqlcode,
1466                                     exceptionStringIn => sqlerrm);
1467           raise;
1468           return(null);
1469     end getHandlerItemId;
1470   function getHandlerItemOrderNumber return integer as
1471     begin
1472       if(getItemClassParMode(itemClassIdIn => engAppRuleItemClassIds(engAppHandlerFirstIndex)) =
1473          ame_util.parallelItems) then
1474         return(1);
1475       else /* The parallelization modes is ame_util.serialItems. */
1476         return(1 + getItemOffset(itemClassIdIn => engAppRuleItemClassIds(engAppHandlerFirstIndex),
1477                                  itemIdIn => engAppAppItemIds(engAppHandlerFirstIndex)));
1478       end if;
1479       exception
1480         when others then
1481           ame_util.runtimeException(packageNameIn => 'ame_engine',
1482                                     routineNameIn => 'getHandlerItemOrderNumber',
1483                                     exceptionNumberIn => sqlcode,
1484                                     exceptionStringIn => sqlerrm);
1485           raise;
1486           return(null);
1487     end getHandlerItemOrderNumber;
1488   function getHandlerOccurrence(nameIn in varchar2,
1489                                 itemClassIn in varchar2 default null,
1490                                 itemIdIn in varchar2 default null,
1491                                 actionTypeIdIn in integer default null,
1492                                 groupOrChainIdIn in integer default null) return integer as
1493     engStApproversCount integer;
1494     itemClass ame_temp_old_approver_lists.item_class%type;
1495     itemId ame_temp_old_approver_lists.item_id%type;
1496     actionTypeId integer;
1497     groupOrChainId integer;
1498     occurrence integer;
1499     begin
1500       engStApproversCount := engStApprovers.count;
1501       /* Handle the empty-list case first. */
1502         if(engStApproversCount = 0) then
1503           return(1);
1504         end if;
1505       /* Determine which chain of authority to match. */
1506       if(itemClassIn is null or
1507          itemIdIn is null or
1508          actionTypeIdIn is null or
1509          groupOrChainIdIn is null) then
1510         /*
1511           If we're not trying to match an inserted approver with nullInsertionActionTypeId and
1512           nullInsertionGroupOrChainId, and one of the input arguments is null, match the most
1513           recently added group or chain.
1514         */
1515         for i in reverse 1 .. engStApproversCount loop
1516           if(engStApprovers(i).action_type_id <> ame_util.nullInsertionActionTypeId and
1517              engStApprovers(i).group_or_chain_id <> ame_util.nullInsertionGroupOrChainId and
1518              engStApprovers(i).item_class is not null and
1519              engStApprovers(i).item_id is not null and
1520              engStApprovers(i).action_type_id is not null and
1521              engStApprovers(i).group_or_chain_id is not null) then
1522             itemClass := engStApprovers(i).item_class;
1523             itemId := engStApprovers(i).item_id;
1524             actionTypeId := engStApprovers(i).action_type_id;
1525             groupOrChainId := engStApprovers(i).group_or_chain_id;
1526             exit;
1527           end if;
1528         end loop;
1529       else
1530         itemClass := itemClassIn;
1531         itemId := itemIdIn;
1532         actionTypeId := actionTypeIdIn;
1533         groupOrChainId := groupOrChainIdIn;
1534       end if;
1535       if(itemClass is null) then
1536         /*
1537           One of the input arguments is null, and all approvers in the list have nullInsertionActionTypeId and
1538           nullInsertionGroupOrChainId.  So these are the only action-type ID and group-or-chain ID we can match.
1539           In this case, match the item class and item ID of the most recent insertion.
1540         */
1541         itemClass := engStApprovers(engStApproversCount).item_class;
1542         itemId := engStApprovers(engStApproversCount).item_id;
1543         actionTypeId := engStApprovers(engStApproversCount).action_type_id;
1544         groupOrChainId := engStApprovers(engStApproversCount).group_or_chain_id;
1545       end if;
1546       /* Now count matches within the target item class, item ID, action-type ID, and group-or-chain ID. */
1547       occurrence := 1;
1548       for i in 1 .. engStApproversCount loop
1549         /*
1550           The order of the comparisons in the if statement below is significant for efficiency.
1551           (Most of the time, the names won't match, and that ends the comparison for engStApprovers(i).)
1552           (We could stop the comparison upon leaving the target item's approver list, but this would
1553           generally take more work than it would save.)
1554         */
1555         if(engStApprovers(i).name = nameIn and
1556            engStApprovers(i).group_or_chain_id = groupOrChainId and
1557            engStApprovers(i).action_type_id = actionTypeId and
1558            engStApprovers(i).item_id = itemId and
1559            engStApprovers(i).item_class = itemClass) then
1560           occurrence := occurrence + 1;
1561         end if;
1562       end loop;
1563       return(occurrence);
1564       exception
1565         when others then
1566           ame_util.runtimeException(packageNameIn => 'ame_engine',
1567                                     routineNameIn => 'getHandlerOccurrence',
1568                                     exceptionNumberIn => sqlcode,
1569                                     exceptionStringIn => sqlerrm);
1570           raise;
1571           return(null);
1572     end getHandlerOccurrence;
1573   function getHandlerRuleType return integer as
1574     begin
1575       return(engAppRuleTypes(engAppHandlerFirstIndex));
1576       exception
1577         when others then
1578           ame_util.runtimeException(packageNameIn => 'ame_engine',
1579                                     routineNameIn => 'getHandlerRuleType',
1580                                     exceptionNumberIn => sqlcode,
1581                                     exceptionStringIn => sqlerrm);
1582           raise;
1583           return(null);
1584     end getHandlerRuleType;
1585   function getHandlerState(handlerNameIn in varchar2,
1586                            parameterIn in varchar2 default null) return varchar2 as
1587     handlerName ame_temp_handler_states.handler_name%type;
1588     tempState ame_temp_handler_states.state%type;
1589     begin
1590       handlerName := upper(handlerNameIn);
1591       select state
1592         into tempState
1593         from ame_temp_handler_states
1594         where
1595           handler_name = handlerName and
1596           ((application_id is null and engAmeApplicationId is null) or
1597            (application_id = engAmeApplicationId)) and
1598           ((parameter is null and parameterIn is null) or
1599            (parameter = parameterIn)) and
1600           rownum < 2; /* Avoids second fetch otherwise required by ANSI standard to check for too many rows. */
1601       return(tempState);
1602       exception
1603         when no_data_found then
1604           return(null);
1605         when others then
1606           ame_util.runtimeException(packageNameIn => 'ame_engine',
1607                                     routineNameIn => 'getHandlerState',
1608                                     exceptionNumberIn => sqlcode,
1609                                     exceptionStringIn => sqlerrm);
1610           raise;
1611           return(null);
1612     end getHandlerState;
1613   function getHandlerSublistOrderNum return integer as
1614     handlerAuthority ame_util.charType;
1615     itemClassSublistMode ame_util.charType;
1616     begin
1617       handlerAuthority := getHandlerAuthority;
1618       itemClassSublistMode := getItemClassSublistMode(itemClassIdIn => engAppRuleItemClassIds(engAppHandlerFirstIndex));
1619       if(itemClassSublistMode = ame_util.serialSublists) then
1620         if(handlerAuthority = ame_util.preApprover) then
1621           return(1);
1622         elsif(handlerAuthority = ame_util.authorityApprover) then
1623           return(2);
1624         else
1625           return(3);
1626         end if;
1627       elsif(itemClassSublistMode = ame_util.parallelSublists) then
1628         return(1);
1629       elsif(itemClassSublistMode = ame_util.preFirst) then
1630         if(handlerAuthority = ame_util.preApprover) then
1631           return(1);
1632         else
1633           return(2);
1634         end if;
1635       else
1636         if(handlerAuthority = ame_util.postApprover) then
1637           return(2);
1638         else
1639           return(1);
1640         end if;
1641       end if;
1642       exception
1643         when others then
1644           ame_util.runtimeException(packageNameIn => 'ame_engine',
1645                                     routineNameIn => 'getHandlerSublistOrderNum',
1646                                     exceptionNumberIn => sqlcode,
1647                                     exceptionStringIn => sqlerrm);
1648           raise;
1649           return(null);
1650     end getHandlerSublistOrderNum;
1651   function getHeaderAttValue1(attributeIdIn in integer) return varchar2 as
1652     begin
1653       return(engAttributeValues1(engAttributeValueIndexes(attributeIdIn)));
1654       exception
1655         when others then
1656           ame_util.runtimeException(packageNameIn => 'ame_engine',
1657                                     routineNameIn => 'getHeaderAttValue1',
1658                                     exceptionNumberIn => sqlcode,
1659                                     exceptionStringIn => sqlerrm);
1660           raise;
1661           return(null);
1662     end getHeaderAttValue1;
1663   function getTestVariantAttValue(attributeIdIn in integer,
1664                                  itemClassIdIn  in integer,
1665                                  itemIdIn       in varchar2) return number as
1666     tempValue ame_util.attributeValueType;
1667     begin
1668       select attribute_value_1 into tempValue from ame_test_trans_att_values
1669         where application_id = engAmeApplicationId
1670           and transaction_id = engTransactionId
1671           and attribute_id = attributeIdIn
1672           and item_class_id = itemClassIdIn
1673           and item_id    = itemIdIn;
1674       return tempValue;
1675       exception
1676         when no_data_found then
1677           begin
1678             select attribute_value_1
1679               into tempValue
1680               from ame_test_trans_att_values
1681              where application_id = engAmeApplicationId
1682                and transaction_id = engTransactionId
1683                and attribute_id = attributeIdIn
1684                and item_class_id = getItemClassId(ame_util.headerItemClassName)
1685                and item_id    = engTransactionId;
1686             return tempValue;
1687           exception
1688             when others then
1689               ame_util.runtimeException(packageNameIn => 'ame_engine',
1690                                         routineNameIn => 'getTestVariantAttValue',
1691                                         exceptionNumberIn => sqlcode,
1692                                         exceptionStringIn => sqlerrm);
1693               raise;
1694               return(null);
1695           end;
1696         when others then
1697           ame_util.runtimeException(packageNameIn => 'ame_engine',
1698                                     routineNameIn => 'getTestVariantAttValue',
1699                                     exceptionNumberIn => sqlcode,
1700                                     exceptionStringIn => sqlerrm);
1701           raise;
1702           return(null);
1703     end getTestVariantAttValue;
1704   function getHeaderAttValue2(attributeNameIn in varchar2) return varchar2 as
1705     attributeId integer;
1706     begin
1707       if engIsTestTransaction then
1708         attributeId := getAttributeIdByName(attributeNameIn => attributeNameIn);
1709         if checkAttributeVariant(attributeId) = ame_util.booleanTrue then
1710            return getTestVariantAttValue(attributeIdIn => attributeId
1711                                        ,itemClassIdIn => engAppRuleItemClassIds(engAppHandlerFirstIndex)
1712                                        ,itemIdIn => engAppAppItemIds(engAppHandlerFirstIndex));
1713         else
1714           return(engAttributeValues1(engAttributeValueIndexes(getAttributeIdByName(attributeNameIn => attributeNameIn))));
1715         end if;
1716       else
1717         if(engAttributeVariant.exists(getAttributeIdByName(attributeNameIn => attributeNameIn))) then
1718           return(getVariantAttributeValue(attributeIdIn => getAttributeIdByName(attributeNameIn => attributeNameIn),
1719                                           itemClassIn => getItemClassName(itemClassIdIn => engAppRuleItemClassIds(engAppHandlerFirstIndex)),
1720                                           itemIdIn => engAppAppItemIds(engAppHandlerFirstIndex)));
1721         else
1722           return(engAttributeValues1(engAttributeValueIndexes(getAttributeIdByName(attributeNameIn => attributeNameIn))));
1723         end if;
1724       end if;
1725       exception
1726         when others then
1727           ame_util.runtimeException(packageNameIn => 'ame_engine',
1728                                     routineNameIn => 'getHeaderAttValue2',
1729                                     exceptionNumberIn => sqlcode,
1730                                     exceptionStringIn => sqlerrm);
1731           raise;
1732           return(null);
1733     end getHeaderAttValue2;
1734   function getItemAttValue1(attributeIdIn in integer,
1735                             itemIdIn in varchar2) return varchar2 as
1736     begin
1737       return(engAttributeValues1(engAttributeValueIndexes(attributeIdIn) +
1738                                  getItemOffset(itemClassIdIn => engAttributeItemClassIds(attributeIdIn),
1739                                                itemIdIn => itemIdIn)));
1740       exception
1741         when others then
1742           ame_util.runtimeException(packageNameIn => 'ame_engine',
1743                                     routineNameIn => 'getItemAttValue1',
1744                                     exceptionNumberIn => sqlcode,
1745                                     exceptionStringIn => sqlerrm);
1746           raise;
1747           return(null);
1748     end getItemAttValue1;
1749   function getItemAttValue2(attributeNameIn in varchar2,
1750                             itemIdIn in varchar2) return varchar2 as
1751     attributeId integer;
1752     begin
1753       attributeId := getAttributeIdByName(attributeNameIn => attributeNameIn);
1754       return(engAttributeValues1(engAttributeValueIndexes(attributeId) +
1755                                   getItemOffset(itemClassIdIn => engAttributeItemClassIds(attributeId),
1756                                                 itemIdIn => itemIdIn)));
1757       exception
1758         when others then
1759           ame_util.runtimeException(packageNameIn => 'ame_engine',
1760                                     routineNameIn => 'getItemAttValue2',
1761                                     exceptionNumberIn => sqlcode,
1762                                     exceptionStringIn => sqlerrm);
1763           raise;
1764           return(null);
1765     end getItemAttValue2;
1766   function getItemClassId(itemClassNameIn in varchar2) return integer as
1767     begin
1768       for itemClassIndex in 1 .. engItemClassNames.count loop
1769         if(engItemClassNames(itemClassIndex) = itemClassNameIn) then
1770           return(engItemClassIds(itemClassIndex));
1771         end if;
1772       end loop;
1773       return(null);
1774       exception
1775         when others then
1776           ame_util.runtimeException(packageNameIn => 'ame_engine',
1777                                     routineNameIn => 'getItemClassId',
1778                                     exceptionNumberIn => sqlcode,
1779                                     exceptionStringIn => sqlerrm);
1780           raise;
1781           return(null);
1782     end getItemClassId;
1783   function getItemClassName(itemClassIdIn in integer) return varchar2 as
1784     begin
1785       return(engItemClassNames(engItemClassIndexes(itemClassIdIn)));
1786       exception
1787         when others then
1788           ame_util.runtimeException(packageNameIn => 'ame_engine',
1789                                     routineNameIn => 'getItemClassName',
1790                                     exceptionNumberIn => sqlcode,
1791                                     exceptionStringIn => sqlerrm);
1792           raise;
1793           return(null);
1794     end getItemClassName;
1795   function getItemClassOrderNumber(itemClassIdIn in integer) return integer as
1796     begin
1797       return(engItemClassOrderNumbers(engItemClassIndexes(itemClassIdIn)));
1798       exception
1799         when others then
1800           ame_util.runtimeException(packageNameIn => 'ame_engine',
1801                                     routineNameIn => 'getItemClassOrderNumber',
1802                                     exceptionNumberIn => sqlcode,
1803                                     exceptionStringIn => sqlerrm);
1804           raise;
1805           return(null);
1806     end getItemClassOrderNumber;
1807   function getItemClassParMode(itemClassIdIn in integer) return varchar2 as
1808     begin
1809       return(engItemClassParModes(engItemClassIndexes(itemClassIdIn)));
1810       exception
1811         when others then
1812           ame_util.runtimeException(packageNameIn => 'ame_engine',
1813                                     routineNameIn => 'getItemClassParMode',
1814                                     exceptionNumberIn => sqlcode,
1815                                     exceptionStringIn => sqlerrm);
1816           raise;
1817           return(null);
1818     end getItemClassParMode;
1819   function getItemClassSublistMode(itemClassIdIn in integer) return varchar2 as
1820     begin
1821       return(engItemClassSublistModes(engItemClassIndexes(itemClassIdIn)));
1822       exception
1823         when others then
1824           ame_util.runtimeException(packageNameIn => 'ame_engine',
1825                                     routineNameIn => 'getItemClassSublistMode',
1826                                     exceptionNumberIn => sqlcode,
1827                                     exceptionStringIn => sqlerrm);
1828           raise;
1829           return(null);
1830     end getItemClassSublistMode;
1831   function getItemIndex(itemClassIdIn in integer,
1832                         itemIdIn in varchar2) return integer as
1833     errorCode integer;
1834     errorMessage ame_util.longestStringType;
1835     firstItemIndex integer;
1836     itemClassIndex integer;
1837     noIndexException exception;
1838     begin
1839       itemClassIndex := engItemClassIndexes(itemClassIdIn);
1840       firstItemIndex := engItemClassItemIdIndexes(itemClassIndex);
1841       for i in firstItemIndex .. (firstItemIndex + engItemCounts(itemClassIndex) - 1) loop
1842         if(engItemIds(i) = itemIdIn) then
1843           return(i);
1844         end if;
1845       end loop;
1846       raise noIndexException;
1847       exception
1848         when noIndexException then
1849           errorCode := -20001;
1850           errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
1851                                               messageNameIn => 'AME_400682_ENG_INV_ITEM_OFFSET');
1852           ame_util.runtimeException(packageNameIn => 'ame_engine',
1853                                     routineNameIn => 'getItemIndex',
1854                                     exceptionNumberIn => errorCode,
1855                                     exceptionStringIn => errorMessage);
1856           raise_application_error(errorCode,
1857                                   errorMessage);
1858           return(null);
1859         when others then
1860           ame_util.runtimeException(packageNameIn => 'ame_engine',
1861                                     routineNameIn => 'getItemIndex',
1862                                     exceptionNumberIn => sqlcode,
1863                                     exceptionStringIn => sqlerrm);
1864           raise;
1865           return(null);
1866     end getItemIndex;
1867   function getItemOffset(itemClassIdIn in integer,
1868                          itemIdIn in varchar2) return integer as
1869     errorCode integer;
1870     errorMessage ame_util.longestStringType;
1871     firstItemIndex integer;
1872     itemClassIndex integer;
1873     noOffsetException exception;
1874     begin
1875       itemClassIndex := engItemClassIndexes(itemClassIdIn);
1876       firstItemIndex := engItemClassItemIdIndexes(itemClassIndex);
1877       for i in firstItemIndex .. (firstItemIndex + engItemCounts(itemClassIndex) - 1) loop
1878         if(engItemIds(i) = itemIdIn) then
1879           return(i - firstItemIndex);
1880         end if;
1881       end loop;
1882       raise noOffsetException;
1883       exception
1884         when noOffsetException then
1885           errorCode := -20001;
1886           errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
1887                                               messageNameIn => 'AME_400682_ENG_INV_ITEM_OFFSET');
1888           ame_util.runtimeException(packageNameIn => 'ame_engine',
1889                                     routineNameIn => 'getItemOffset',
1890                                     exceptionNumberIn => errorCode,
1891                                     exceptionStringIn => errorMessage);
1892           raise_application_error(errorCode,
1893                                   errorMessage);
1894           return(null);
1895         when others then
1896           ame_util.runtimeException(packageNameIn => 'ame_engine',
1897                                     routineNameIn => 'getItemOffset',
1898                                     exceptionNumberIn => sqlcode,
1899                                     exceptionStringIn => sqlerrm);
1900           raise;
1901           return(null);
1902     end getItemOffset;
1903   function getItemOrderNumber(itemClassNameIn in varchar2,
1904                               itemIdIn in varchar2) return integer as
1905     itemClassId integer;
1906     begin
1907       itemClassId := getItemClassId(itemClassNameIn => itemClassNameIn);
1908       if(getItemClassParMode(itemClassIdIn => itemClassId) = ame_util.parallelItems) then
1909         return(1);
1910       else /* The parallelization modes is ame_util.serialItems. */
1911         return(1 + getItemOffset(itemClassIdIn => itemClassId,
1912                                  itemIdIn => itemIdIn));
1913       end if;
1914       exception
1915         when others then
1916           ame_util.runtimeException(packageNameIn => 'ame_engine',
1917                                     routineNameIn => 'getItemOrderNumber',
1918                                     exceptionNumberIn => sqlcode,
1919                                     exceptionStringIn => sqlerrm);
1920           raise;
1921           return(null);
1922     end getItemOrderNumber;
1923   function getNextInsertionOrder return integer as
1924     maxInsertionOrderNumber number;
1925     begin
1926       select max(insertion_order)
1927         into maxInsertionOrderNumber
1928         from ame_temp_insertions
1929        where transaction_id = engTransactionId
1930          and application_id = engAmeApplicationId;
1931       if maxinsertionOrderNumber is null
1932       then
1933         return 1;
1934       else
1935         return (maxInsertionOrderNumber + 1);
1936       end if;
1937       exception
1938         when others then
1939           ame_util.runtimeException(packageNameIn => 'ame_engine',
1940                                     routineNameIn => 'getNextInsertionOrder',
1941                                     exceptionNumberIn => sqlcode,
1942                                     exceptionStringIn => sqlerrm);
1943           raise;
1944           return(null);
1945     end getNextInsertionOrder;
1946   function getNullActionTypeOrderNumber return integer as
1947     maxOrderNumber integer := 0;
1948     tempIndex integer;
1949     begin
1950       tempIndex := engActionTypeOrderNumbers.first;
1951       while(tempIndex is not null) loop
1952         if(maxOrderNumber is null or
1953            engActionTypeOrderNumbers(tempIndex) < maxOrderNumber) then
1954           maxOrderNumber := engActionTypeOrderNumbers(tempIndex);
1955         end if;
1956         tempIndex := engActionTypeOrderNumbers.next(tempIndex);
1957       end loop;
1958       return(maxOrderNumber + 1);
1959       exception
1960         when others then
1961           ame_util.runtimeException(packageNameIn => 'ame_engine',
1962                                     routineNameIn => 'getNullActionTypeOrderNumber',
1963                                     exceptionNumberIn => sqlcode,
1964                                     exceptionStringIn => sqlerrm);
1965           raise;
1966           return(null);
1967     end getNullActionTypeOrderNumber;
1968   function getRuntimeGroupCount(groupIdIn in integer) return integer as
1969     tempIndex integer;
1970     begin
1971       tempIndex := 0; /* pre-increment */
1972       -- Check if group is defined or has to be re run for every item class/item ID
1973       if(not engGroupUseItemBind.exists(groupIdIn)) then
1974         fetchRuntimeGroup(groupIdIn => groupIdIn);
1975       elsif (engGroupUseItemBind(groupIdIn) = ame_util.booleanTrue) then
1976         fetchRuntimeGroup(groupIdIn => groupIdIn);
1977       end if;
1978       /* Group membership must exist in  engGroupMemberGroupIds now. */
1979       for i in 1 .. engGroupMemberGroupIds.count loop
1980         if(engGroupMemberGroupIds(i) = groupIdIn) then
1981           tempIndex := tempIndex + 1;
1982         elsif(tempIndex > 0) then
1983           /* The group was found and has been passed. */
1984           return(tempIndex);
1985         end if;
1986       end loop;
1987       exception
1988         when others then
1989           ame_util.runtimeException(packageNameIn => 'ame_engine',
1990                                     routineNameIn => 'getRuntimeGroupCount',
1991                                     exceptionNumberIn => sqlcode,
1992                                     exceptionStringIn => sqlerrm);
1993           raise;
1994           return(null);
1995     end getRuntimeGroupCount;
1996   function getSublistOrderNum(itemClassNameIn in varchar2,
1997                               authorityIn in varchar2) return integer as
1998     itemClassSublistMode ame_util.charType;
1999     begin
2000       itemClassSublistMode :=
2001         getItemClassSublistMode(itemClassIdIn => getItemClassId(itemClassNameIn => itemClassNameIn));
2002       if(itemClassSublistMode = ame_util.serialSublists) then
2003         if(authorityIn = ame_util.preApprover) then
2004           return(1);
2005         elsif(authorityIn = ame_util.authorityApprover) then
2006           return(2);
2007         else
2008           return(3);
2009         end if;
2010       elsif(itemClassSublistMode = ame_util.parallelSublists) then
2011         return(1);
2012       elsif(itemClassSublistMode = ame_util.preFirst) then
2013         if(authorityIn = ame_util.preApprover) then
2014           return(1);
2015         else
2016           return(2);
2017         end if;
2018       else
2019         if(authorityIn = ame_util.postApprover) then
2020           return(2);
2021         else
2022           return(1);
2023         end if;
2024       end if;
2025       exception
2026         when others then
2027           ame_util.runtimeException(packageNameIn => 'ame_engine',
2028                                     routineNameIn => 'getSublistOrderNum',
2029                                     exceptionNumberIn => sqlcode,
2030                                     exceptionStringIn => sqlerrm);
2031           raise;
2032           return(null);
2033     end getSublistOrderNum;
2034   function getTransactionId return varchar2 as
2035     begin
2036       return(engTransactionID);
2037       exception
2038         when others then
2039           ame_util.runtimeException(packageNameIn => 'ame_engine',
2040                                     routineNameIn => 'getTransactionId',
2041                                     exceptionNumberIn => sqlcode,
2042                                     exceptionStringIn => sqlerrm);
2043           raise;
2044           return(null);
2045     end getTransactionId;
2046   function getTransactionTypeId return varchar2 as
2047     begin
2048       return(engTransactionTypeID);
2049       exception
2050         when others then
2051           ame_util.runtimeException(packageNameIn => 'ame_engine',
2052                                     routineNameIn => 'getTransactionTypeId',
2053                                     exceptionNumberIn => sqlcode,
2054                                     exceptionStringIn => sqlerrm);
2055           raise;
2056           return(null);
2057     end getTransactionTypeId;
2058   /********************************** sort functions **********************************/
2059   function compareApplicableRules(index1In in integer,
2060                                   index2In in integer,
2061                                   compareActionTypesIn in boolean) return boolean as
2062     /* Returns true if the applicable rule at the first index weakly precedes the second. */
2063     actionTypeId1 integer;
2064     actionTypeId2 integer;
2065     itemClassId1 integer;
2066     itemClassId2 integer;
2067     begin
2068       itemClassId1 := engAppRuleItemClassIds(index1In);
2069       itemClassId2 := engAppRuleItemClassIds(index2In);
2070       /* Account for the possibility that one or both rules may have null item-class IDs. */
2071       if(itemClassId1 is null) then
2072         if(itemClassId2 is not null) then
2073           return(false);
2074         end if;
2075       else /* itemClassId1 is not null. */
2076         if(itemClassId2 is null) then
2077           return(true);
2078         else /* Both item-class IDs are non-null. */
2079           /* item-class order number */
2080           if(engItemClassOrderNumbers(engItemClassIndexes(itemClassId1)) >
2081              engItemClassOrderNumbers(engItemClassIndexes(itemClassId2))) then
2082             return(false);
2083           end if;
2084           if(engItemClassOrderNumbers(engItemClassIndexes(itemClassId1)) <
2085              engItemClassOrderNumbers(engItemClassIndexes(itemClassId2))) then
2086             return(true);
2087           end if;
2088           /* item-class ID */
2089           if(itemClassId1 > itemClassId2) then
2090             return(false);
2091           end if;
2092           if(itemClassId1 < itemClassId2) then
2093             return(true);
2094           end if;
2095         end if;
2096       end if;
2097       /* item ID */
2098       if(engAppAppItemIds(index1In) > engAppAppItemIds(index2In)) then
2099         return(false);
2100       end if;
2101       if(engAppAppItemIds(index1In) < engAppAppItemIds(index2In)) then
2102         return(true);
2103       end if;
2104       /* rule type */
2105       if(engAppRuleTypes(index1In) > engAppRuleTypes(index2In)) then
2106         return(false);
2107       end if;
2108       /*
2109         The second rule-type comparison is only necessary if compareActionTypesIn is true;
2110         otherwise, we return true regardless of the outcome of the second rule-type comparison.
2111         So include it within the if(compareActionTypesIn) below.
2112       /* optional action-type comparisons */
2113       if(compareActionTypesIn) then
2114         if(engAppRuleTypes(index1In) < engAppRuleTypes(index2In)) then
2115           return(true);
2116         end if;
2117         /* Do the action-type comparisons. */
2118         actionTypeId1 := engAppActionTypeIds(index1In);
2119         actionTypeId2 := engAppActionTypeIds(index2In);
2120         /* action-type order numbers */
2121         if(engActionTypeOrderNumbers(actionTypeId1) >
2122            engActionTypeOrderNumbers(actionTypeId2)) then
2123           return(false);
2124         end if;
2125         if(engActionTypeOrderNumbers(actionTypeId1) <
2126            engActionTypeOrderNumbers(actionTypeId2)) then
2127           return(true);
2128         end if;
2129         /* action-type ID */
2130         if(actionTypeId1 > actionTypeId2) then
2131           return(false);
2132         end if;
2133         /*
2134           The second comparison on action-type ID is unnecessary, because whether it succeeds
2135           or fails, we return true.
2136         */
2137       end if;
2138       return(true);
2139         exception
2140           when others then
2141             ame_util.runtimeException(packageNameIn => 'ame_engine',
2142                                       routineNameIn => 'compareApplicableRules',
2143                                       exceptionNumberIn => sqlcode,
2144                                       exceptionStringIn => sqlerrm);
2145             raise;
2146             return(false);
2147     end compareApplicableRules;
2148   /*************************************************************************************
2149   procedures
2150   *************************************************************************************/
2151   procedure addApprover(approverIn in ame_util.approverRecord2) as
2152     errorCode integer;
2153     errorMessage ame_util.longestStringType;
2154     listTooLongException exception;
2155     nullFieldException exception;
2156     begin
2157       if(engStApprovers.count > 2500) then
2158         raise listTooLongException;
2159       end if;
2160       checkApprover(approverIn => approverIn);
2161       if(approverIn.name is null or
2162          approverIn.orig_system is null or
2163          approverIn.orig_system_id is null or
2164          approverIn.display_name is null or
2165          approverIn.approver_category is null or
2166          approverIn.api_insertion is null or
2167          approverIn.authority is null or
2168          approverIn.action_type_id is null or
2169          approverIn.group_or_chain_id is null or
2170          approverIn.occurrence is null or
2171          approverIn.source is null or
2172          approverIn.item_class is null or
2173          approverIn.item_id is null or
2174          approverIn.item_class_order_number is null or
2175          approverIn.item_order_number is null or
2176          approverIn.sub_list_order_number is null or
2177          approverIn.action_type_order_number is null or
2178          approverIn.group_or_chain_order_number is null or
2179          approverIn.member_order_number is null) then
2180         raise nullFieldException;
2181       end if;
2182       ame_util.copyApproverRecord2(approverRecord2In => approverIn,
2183                                    approverRecord2Out => engStApprovers(engStApprovers.count + 1));
2184       /* Add the approver to the tree whenever he is added to the approver list */
2185       /* Approvers location in list is engStApprovers.count                     */
2186       /* Add the approver as the last approver among the approvers with same    */
2187       /* order number                                                           */
2188       if engPrepareApproverTree then
2189         addApproverToTree
2190             (approverRecordIn    => engStApprovers(engStApprovers.count)
2191             ,approverIndexIn     => engStApprovers.count
2192             ,approverLocationIn  => ame_util.lastAmongEquals);
2193       end if;
2194       exception
2195         when listTooLongException then
2196           errorCode := -20001;
2197           errorMessage :=
2198           ame_util.getMessage(applicationShortNameIn => 'PER',
2199                               messageNameIn => 'AME_400118_ENG_LOOP_CHA_AUTH');
2200           ame_util.runtimeException(packageNameIn => 'ame_engine',
2201                                     routineNameIn => 'addApprover',
2202                                     exceptionNumberIn => errorCode,
2203                                     exceptionStringIn => errorMessage);
2204           raise_application_error(errorCode,
2205                                   errorMessage);
2206         when nullFieldException then
2207           errorCode := -20001;
2208           errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
2209                                               messageNameIn => 'AME_400683_APPR_REC_INV');
2210           ame_util.runtimeException(packageNameIn => 'ame_engine',
2211                                     routineNameIn => 'addApprover',
2212                                     exceptionNumberIn => errorCode,
2213                                     exceptionStringIn => errorMessage);
2214           raise_application_error(errorCode,
2215                                   errorMessage);
2216         when others then
2217           ame_util.runtimeException(packageNameIn => 'ame_engine',
2218                                     routineNameIn => 'addApprover',
2219                                     exceptionNumberIn => sqlcode,
2220                                     exceptionStringIn => sqlerrm);
2221           raise;
2222     end addApprover;
2223   procedure addApproversTodevList(approverRecordIndexIn in integer) is
2224    tempCount integer;
2225   begin
2226     if engTempReason is not null or engTempDate is not null then
2227       engDeviationResultList(approverRecordIndexIn).reason := engTempReason;
2228       engDeviationResultList(approverRecordIndexIn).effectiveDate := engTempDate;
2229     end if;
2230     engTempReason := null;
2231     engTempDate := null;
2232   exception
2233     when others then
2234       ame_util.runtimeException(packageNameIn => 'ame_engine',
2235                                 routineNameIn => 'addApproversTodevList',
2236                                 exceptionNumberIn => sqlcode,
2237                                 exceptionStringIn => sqlerrm);
2238   end addApproversTodevList;
2239   /* This procedure is used to add an approver to the approver tree */
2240   procedure addApproverToTree
2241     (approverRecordIn   in            ame_util.approverRecord2
2242     ,approverIndexIn    in            integer
2243     ,approverLocationIn in            boolean default ame_util.lastAmongEquals) is
2244     orderNumbers                 ame_util.idList;
2245     treeLevelIds                 ame_util.stringList;
2246     approverIndexs               ame_util.idList;
2247     previousTreeNodeIndex        integer;
2248     currentTreeNodeIndex         integer;
2249     newTreeNodeIndex             integer;
2250     newTreeNode                  ame_util.approverTreeRecord;
2251     currentSiblingTreeNodeIndex  integer;
2252     lowerOrderLastSiblingIndex   integer;
2253     higherOrderFirstSiblingIndex integer;
2254     sameOrderFirstSiblingIndex   integer;
2255     sameOrderLastSiblingIndex    integer;
2256     currentTreeNodeFound         boolean;
2257   begin
2258     /* Initialise the tree with the transaction level node if the tree */
2259     /* is not yet built.The tree level node will have min_order of 1   */
2260     /* which is the minimum allowed approver order number              */
2261     if engStApproversTree.count = 0 then
2262       newTreeNode.parent_index := ame_util.noParentIndex;
2263       newTreeNode.child_index := ame_util.noChildIndex;
2264       newTreeNode.sibling_index := ame_util.noSiblingIndex;
2265       newTreeNode.approver_index := ame_util.noApproverIndex;
2266       newTreeNode.tree_level_id := -1;
2267       newTreeNode.order_number := -1;
2268       newTreeNode.min_order := ame_util.minimumApproverOrderNumber;
2269       newTreeNode.is_suspended := ame_util.booleanFalse;
2270 --      newTreeNode.repeated_index := -1;
2271       newTreeNode.tree_level := 0;
2272       engStApproversTree(1)  := newTreeNode;
2273     end if;
2274     /* For each tree level assign the node order number, unique tree level */
2275     /* ids and the approver indices                                        */
2276     orderNumbers(1) := approverRecordIn.item_class_order_number;
2277     orderNumbers(2) := approverRecordIn.item_order_number;
2278     orderNumbers(3) := approverRecordIn.sub_list_order_number;
2279     orderNumbers(4) := approverRecordIn.action_type_order_number;
2280     orderNumbers(5) := approverRecordIn.group_or_chain_order_number;
2281     orderNumbers(6) := approverRecordIn.member_order_number;
2282     treeLevelIds(1) := approverRecordIn.item_class;
2283     treeLevelIds(2) := approverRecordIn.item_id;
2284     treeLevelIds(3) := approverRecordIn.authority;
2285     treeLevelIds(4) := to_char(approverRecordIn.action_type_id);
2286     treeLevelIds(5) := to_char(approverRecordIn.group_or_chain_id);
2287     treeLevelIds(6) := approverRecordIn.name;
2288     approverIndexs(1) := ame_util.noApproverIndex;
2289     approverIndexs(2) := ame_util.noApproverIndex;
2290     approverIndexs(3) := ame_util.noApproverIndex;
2291     approverIndexs(4) := ame_util.noApproverIndex;
2292     approverIndexs(5) := ame_util.noApproverIndex;
2293     approverIndexs(6) := approverIndexIn;
2294     /* Starting with the transaction node traverse the tree through the    */
2295     /* item class,item,sublist,action type,group or chain and finally      */
2296     /* insert the approver into the tree.In the way if any of other nodes  */
2297     /* are missing create them.                                            */
2298     previousTreeNodeIndex := 1;
2299     for i in 1 .. 6 loop
2300       if engStApproversTree(previousTreeNodeIndex).child_index
2301                                                    = ame_util.noChildIndex then
2302         newTreeNode.parent_index := previousTreeNodeIndex;
2303         newTreeNode.sibling_index := ame_util.noSiblingIndex;
2304         newTreeNode.child_index := ame_util.noChildIndex;
2305         newTreeNode.approver_index := approverIndexs(i);
2306         newTreeNode.tree_level_id := treeLevelIds(i);
2307         newTreeNode.order_number := orderNumbers(i);
2308         newTreeNode.is_suspended := ame_util.booleanFalse;
2309         newTreeNode.tree_level := i;
2310         newTreeNodeIndex := engStApproversTree.last + 1;
2311         engStApproversTree(newTreeNodeIndex) := newTreeNode;
2312         engStApproversTree(previousTreeNodeIndex).child_index := newTreeNodeIndex;
2313         currentTreeNodeIndex := newTreeNodeIndex;
2314       else
2315         currentSiblingTreeNodeIndex :=
2316                              engStApproversTree(previousTreeNodeIndex).child_index;
2317         lowerOrderLastSiblingIndex := -1;
2318         higherOrderFirstSiblingIndex := -1;
2319         sameOrderFirstSiblingIndex := -1;
2320         sameOrderLastSiblingIndex := -1;
2321         currentTreeNodeFound := false;
2322         loop
2323           if engStApproversTree(currentSiblingTreeNodeIndex).order_number
2324                                                               < orderNumbers(i) then
2325             lowerOrderLastSiblingIndex := currentSiblingTreeNodeIndex;
2326           elsif engStApproversTree(currentSiblingTreeNodeIndex).order_number
2327                                                               = orderNumbers(i) then
2328             if engStApproversTree(currentSiblingTreeNodeIndex).tree_level_id
2329                                                               = treeLevelIds(i)
2330                and (i <> 6) then --added for bug 4232137
2331               currentTreeNodeIndex := currentSiblingTreeNodeIndex;
2332               currentTreeNodeFound := true;
2333               exit;
2334             end if;
2335             if sameOrderFirstSiblingIndex = -1 then
2336               sameOrderFirstSiblingIndex := currentSiblingTreeNodeIndex;
2337             end if;
2338             sameOrderLastSiblingIndex := currentSiblingTreeNodeIndex;
2339           elsif engStApproversTree(currentSiblingTreeNodeIndex).order_number
2340                                                               > orderNumbers(i) then
2341             if higherOrderFirstSiblingIndex = -1 then
2342               higherOrderFirstSiblingIndex := currentSiblingTreeNodeIndex;
2343             end if;
2344           end if;
2345           currentSiblingTreeNodeIndex
2346                    := engStApproversTree(currentSiblingTreeNodeIndex).sibling_index;
2347           exit when currentSiblingTreeNodeIndex = ame_util.noSiblingIndex;
2348         end loop;
2349         if not currentTreeNodeFound then
2350           if approverLocationIn then
2351             /* approverLocationIn is ame_util.firstAmongEquals */
2352             newTreeNode.parent_index := previousTreeNodeIndex;
2353             if sameOrderFirstSiblingIndex = -1 then
2354               newTreeNode.sibling_index := higherOrderFirstSiblingIndex;
2355             else
2356               newTreeNode.sibling_index := sameOrderFirstSiblingIndex;
2357             end if;
2358             newTreeNode.child_index := ame_util.noChildIndex;
2359             newTreeNode.approver_index := approverIndexs(i);
2360             newTreeNode.tree_level_id := treeLevelIds(i);
2361             newTreeNode.order_number := orderNumbers(i);
2362             newTreeNode.is_suspended := ame_util.booleanFalse;
2363             newTreeNode.tree_level := i;
2364             newTreeNodeIndex := engStApproversTree.last + 1;
2365             engStApproversTree(newTreeNodeIndex) := newTreeNode;
2366             if lowerOrderLastSiblingIndex = -1 then
2367               engStApproversTree(previousTreeNodeIndex).child_index := newTreeNodeIndex;
2368             else
2369               engStApproversTree(lowerOrderLastSiblingIndex).sibling_index := newTreeNodeIndex;
2370             end if;
2371             currentTreeNodeIndex := newTreeNodeIndex;
2372           else
2373             /* approverLocationIn is ame_util.lastAmongEquals */
2374             newTreeNode.parent_index := previousTreeNodeIndex;
2375             newTreeNode.sibling_index := higherOrderFirstSiblingIndex;
2376             newTreeNode.child_index := ame_util.noChildIndex;
2377             newTreeNode.approver_index := approverIndexs(i);
2378             newTreeNode.tree_level_id := treeLevelIds(i);
2379             newTreeNode.order_number := orderNumbers(i);
2380             newTreeNode.is_suspended := ame_util.booleanFalse;
2381             newTreeNode.tree_level := i;
2382             newTreeNodeIndex := engStApproversTree.last + 1;
2383             engStApproversTree(newTreeNodeIndex) := newTreeNode;
2384             if sameOrderLastSiblingIndex = -1 and lowerOrderLastSiblingIndex = -1 then
2385               engStApproversTree(previousTreeNodeIndex).child_index := newTreeNodeIndex;
2386             elsif sameOrderLastSiblingIndex = -1 then
2387               engStApproversTree(lowerOrderLastSiblingIndex).sibling_index := newTreeNodeIndex;
2388             else
2389               engStApproversTree(sameOrderLastSiblingIndex).sibling_index := newTreeNodeIndex;
2390             end if;
2391             currentTreeNodeIndex := newTreeNodeIndex;
2392           end if;
2393         end if;
2394       end if;
2395       previousTreeNodeIndex := currentTreeNodeIndex;
2396     end loop;
2397     addApproversTodevList(approverRecordIndexIn => approverIndexIn);
2398   exception
2399     when others then
2400       ame_util.runtimeException(packageNameIn => 'ame_engine',
2401                                 routineNameIn => 'addApproverToTree',
2402                                 exceptionNumberIn => sqlcode,
2403                                 exceptionStringIn => sqlerrm);
2404       raise;
2405   end addApproverToTree;
2406   procedure calculateApproverOrderNumbers as
2407     maximumApproverOrderNumber integer;
2408     transactionApprovalStatus integer;
2409     transactionhasSuspendedItems boolean;
2410     stoppingRule ame_util.stringType;
2411     headerItemRejected boolean;
2412     loopIndex integer;
2413     begin
2414       /* The call to finalizeTree does the following            */
2415       /* 1.Calculate the approver order number                  */
2416       /* 2.Populates the list of rejected items and itemclasses */
2417       /* 3.Returns whether the transaction has rejected Items   */
2418       /* 4.Returns the maximum order number of approvers        */
2419       /* 5.Returns the approval status of the transaction       */
2420       finalizeTree
2421         (parentIndexIn         => 1
2422         ,maximumOrderOut       => maximumApproverOrderNumber
2423         ,approvalStatusOut     => transactionApprovalStatus
2424         ,rejectedItemsExistOut => transactionhasSuspendedItems);
2425       engStApproversTree(1).status := transactionApprovalStatus;
2426       engStApproversTree(1).max_order := maximumApproverOrderNumber;
2427       stoppingRule := ame_engine.getHeaderAttValue2
2428                                  (attributeNameIn => ame_util.rejectionResponseAttribute);
2429       if transactionhasSuspendedItems then
2430         /* Check if any of the suspended item is a header item */
2431         /* If a header item is suspended then it is as good as */
2432         /* the entire transaction being suspended              */
2433         headerItemRejected := false;
2434         for i in 1 .. engStSuspendedItemClasses.count loop
2435           if engStSuspendedItemClasses(i) = ame_util.headerItemClassName then
2436             headerItemRejected := true;
2437             exit;
2438           end if;
2439         end loop;
2440         if stoppingRule = ame_util.stopAllItems or headerItemRejected then
2441           /* Suspend the transaction node */
2442           engStApproversTree(1).is_suspended := ame_util.booleanTrue;
2443         elsif stoppingRule = ame_util.continueAllOtherItems then
2444           /* Suspend all items in the suspended items list */
2445           for i in 1 .. engStSuspendedItems.count loop
2446             /* Approvers Tree can be sparse */
2447             loopIndex := engStApproversTree.first;
2448             loop
2449               if(engStApproversTree(loopIndex).tree_level = 2 and
2450                  engStApproversTree(loopIndex).tree_level_id = engStSuspendedItems(i) and
2451                  engStApproversTree(engStApproversTree(loopIndex).parent_index).tree_level_id
2452                                                          = engStSuspendedItemClasses(i)) then
2453                 engStApproversTree(loopIndex).is_suspended := ame_util.booleanTrue;
2454                 exit;
2455               end if;
2456               exit when loopIndex = engStApproversTree.last;
2457               loopIndex := engStApproversTree.next(loopIndex);
2458             end loop;
2459           end loop;
2460         elsif stoppingRule = ame_util.continueOtherSubItems then
2461           /* Suspend all items in the suspended items list and header item */
2462           for i in 1 .. engStSuspendedItems.count loop
2463             /* Approvers Tree can be sparse */
2464             loopIndex := engStApproversTree.first;
2465             loop
2466               if(engStApproversTree(loopIndex).tree_level = 2 and
2467                  ((engStApproversTree(loopIndex).tree_level_id = engStSuspendedItems(i) and
2468                   engStApproversTree(engStApproversTree(loopIndex).parent_index).tree_level_id
2469                                                         = engStSuspendedItemClasses(i))
2470                                                         or
2471                   (engStApproversTree(engStApproversTree(loopIndex).parent_index).tree_level_id
2472                                                         = ame_util.headerItemClassName))) then
2473                 engStApproversTree(loopIndex).is_suspended := ame_util.booleanTrue;
2474               end if;
2475               exit when loopIndex = engStApproversTree.last;
2476               loopIndex := engStApproversTree.next(loopIndex);
2477             end loop;
2478           end loop;
2479         end if;
2480       end if;
2481       exception
2482         when others then
2483           ame_util.runtimeException(packageNameIn => 'ame_engine',
2484                                     routineNameIn => 'calculateApproverOrderNumbers',
2485                                     exceptionNumberIn => sqlcode,
2486                                     exceptionStringIn => sqlerrm);
2487           raise;
2488     end calculateApproverOrderNumbers;
2489   --+
2490   --+ check Approver
2491   --+
2492   procedure checkApprover(approverIn in ame_util.approverRecord2) is
2493     errorCode integer;
2494     errorMessage ame_util.longestStringType;
2495     tempApproverTypeCount integer;
2496     tempApproverType ame_approver_types.orig_system%type;
2497     invalidApproverException1 exception;
2498     invalidApproverException2 exception;
2499     begin
2500       tempApproverType := approverIn.orig_system;
2501       if tempApproverType like 'FND_RESP%' then
2502         return;
2503       end if;
2504       if getConfigVarValue(ame_util.allowAllApproverTypesConfigVar) = ame_util.yes then
2505         select count(*)
2506           into tempApproverTypeCount
2507           from ame_approver_types
2508          where orig_system = approverIn.orig_system
2509            and sysdate between start_date and end_date;
2510         if tempApproverTypeCount = 0 then
2511           raise invalidApproverException1;
2512         end if;
2513       else
2514         if(tempApproverType in (ame_util.perOrigSystem
2515                                ,ame_util.fndUserOrigSystem )) then
2516           null;
2517         else
2518           raise invalidApproverException2;
2519         end if;
2520       end if;
2521     exception
2522       when invalidApproverException1 then
2523         errorCode := -20001;
2524         errorMessage := 'The Approver '
2525                         ||approverIn.display_name
2526                         ||' belongs to approver type '
2527                         ||approverIn.orig_system
2528                         ||' which is not registered in AME.';
2529         ame_util.runtimeException(packageNameIn => 'ame_engine',
2530                                   routineNameIn => 'checkApprover',
2531                                   exceptionNumberIn => errorCode,
2532                                   exceptionStringIn => errorMessage);
2533         raise_application_error(errorCode,
2534                                   errorMessage);
2535       when invalidApproverException2 then
2536         errorCode := -20001;
2537         errorMessage := 'The Approver '
2538                         ||approverIn.display_name
2539                         ||' belongs to approver type '
2540                         ||approverIn.orig_system
2541                         ||'. And the allowAllApproverTypes configuration variable set to No.';
2542         ame_util.runtimeException(packageNameIn => 'ame_engine',
2543                                   routineNameIn => 'checkApprover',
2544                                   exceptionNumberIn => errorCode,
2545                                   exceptionStringIn => errorMessage);
2546         raise_application_error(errorCode,
2547                                   errorMessage);
2548     end checkApprover;
2549   --+
2550   procedure clearHandlerState(handlerNameIn in varchar2,
2551                               parameterIn in varchar2 default null) as
2552     handlerName ame_temp_handler_states.handler_name%type;
2553     begin
2554       handlerName := upper(handlerNameIn);
2555       delete
2556         from ame_temp_handler_states
2557         where
2558           handler_name = handlerName and
2559           application_id = engAmeApplicationId and
2560           ((parameter is null and parameterIn is null) or
2561            (parameter = parameterIn));
2562       exception
2563         when others then
2564           ame_util.runtimeException(packageNameIn => 'ame_engine',
2565                                     routineNameIn => 'clearHandlerState',
2566                                     exceptionNumberIn => sqlcode,
2567                                     exceptionStringIn => sqlerrm);
2568           raise;
2569     end clearHandlerState;
2570   procedure compactEngAppLists(compactPrioritiesIn in boolean,
2571                                compactActionTypeIdsIn in boolean,
2572                                compactParametersIn in boolean) as
2573     tempCount integer;
2574     tempFirstIndex integer;
2575     tempLastIndex integer;
2576     begin
2577       tempCount := engAppRuleIds.count;
2578       if(tempCount = 0) then
2579         return;
2580       end if;
2581       tempFirstIndex := engAppRuleIds.first;
2582       for i in 1 .. tempCount loop
2583         if(i <> tempFirstIndex) then /* (Don't copy a row onto itself.) */
2584           engAppItemClassIds(i) := engAppItemClassIds(tempFirstIndex);
2585           engAppItemIds(i) := engAppItemIds(tempFirstIndex);
2586           engAppApproverCategories(i) := engAppApproverCategories(tempFirstIndex);
2587           engAppRuleIds(i) := engAppRuleIds(tempFirstIndex);
2588           engRuleAppliedYN(i) := engRuleAppliedYN(tempFirstIndex);
2589           engAppRuleTypes(i) := engAppRuleTypes(tempFirstIndex);
2590           engAppRuleItemClassIds(i) := engAppRuleItemClassIds(tempFirstIndex);
2591           engAppAppItemIds(i) := engAppAppItemIds(tempFirstIndex);
2592           if(compactPrioritiesIn) then
2593             engAppPriorities(i) := engAppPriorities(tempFirstIndex);
2594           end if;
2595           if(compactActionTypeIdsIn) then
2596             engAppActionTypeIds(i) := engAppActionTypeIds(tempFirstIndex);
2597           end if;
2598           if(compactParametersIn) then
2599             engAppParameters(i) := engAppParameters(tempFirstIndex);
2600             engAppParameterTwos(i) := engAppParameterTwos(tempFirstIndex);
2601           end if;
2602         end if;
2603         tempFirstIndex := engAppRuleIds.next(tempFirstIndex);
2604       end loop;
2605       /*
2606         engAppRuleIds.next will set tempFirstIndex null just before the for loop
2607         exits, so we have to set it anew here.
2608       */
2609       tempFirstIndex := tempCount + 1;
2610       tempLastIndex := engAppRuleIds.last;
2611       engAppItemClassIds.delete(tempFirstIndex, tempLastIndex);
2612       engAppItemIds.delete(tempFirstIndex, tempLastIndex);
2613       engAppApproverCategories.delete(tempFirstIndex, tempLastIndex);
2614       engAppRuleIds.delete(tempFirstIndex, tempLastIndex);
2615       engRuleAppliedYN.delete(tempFirstIndex, tempLastIndex);
2616       engAppRuleTypes.delete(tempFirstIndex, tempLastIndex);
2617       engAppRuleItemClassIds.delete(tempFirstIndex, tempLastIndex);
2618       engAppAppItemIds.delete(tempFirstIndex, tempLastIndex);
2619       if(compactPrioritiesIn) then
2620         engAppPriorities.delete(tempFirstIndex, tempLastIndex);
2621       end if;
2622       if(compactActionTypeIdsIn) then
2623         engAppActionTypeIds.delete(tempFirstIndex, tempLastIndex);
2624       end if;
2625       if(compactParametersIn) then
2626         engAppParameters.delete(tempFirstIndex, tempLastIndex);
2627         engAppParameterTwos.delete(tempFirstIndex, tempLastIndex);
2628       end if;
2629       exception
2630         when others then
2631           ame_util.runtimeException(packageNameIn => 'ame_engine',
2632                                     routineNameIn => 'compactEngAppLists',
2633                                     exceptionNumberIn => sqlcode,
2634                                     exceptionStringIn => sqlerrm);
2635           raise;
2636     end compactEngAppLists;
2637   procedure doPerItemRuleEvaluation(itemClassIdIn in integer,
2638                                     itemIndexIn in varchar2) as
2639     currentACUsageConditionIds ame_util.idList;
2640     currentACUsageRuleIds ame_util.idList;
2641     currentConditionRuleCounts ame_util.idList;
2642     tempConditionId integer;
2643     tempConditionId2 integer;
2644     tempHighestRuleCount integer;
2645     tempIndex integer;
2646     tempIndex2 integer;
2647     tempIndex3 integer;
2648     tempPendingRuleIds ame_util.idList;
2649     tempRuleApplies boolean;
2650     tempRuleId integer;
2651     begin
2652       /* Handle the null case (no active conditions) first. */
2653       if(not engACUsageFirstIndexes.exists(itemClassIdIn)) then
2654         return;
2655       end if;
2656       /*
2657         Initialize the current condition usages.  Note that while the currentACUsage local
2658         variables start out as compact lists, the algorithm that iterates through them
2659         deletes them in an unpredictable order, and does not re-compact the lists; so the
2660         algorithm must treat these lists as sparse.
2661       */
2662       tempIndex := 0; /* pre-increment */
2663       if(engACUsageFirstIndexes.exists(itemClassIdIn)) then
2664         for ACUIndex in
2665           engACUsageFirstIndexes(itemClassIdIn) ..
2666           (engACUsageFirstIndexes(itemClassIdIn) + engACUsageItemClassCounts(itemClassIdIn) - 1) loop
2667           tempIndex := tempIndex + 1;
2668           currentACUsageConditionIds(tempIndex) := engACUsageConditionIds(ACUIndex);
2669           currentACUsageRuleIds(tempIndex) := engACUsageRuleIds(ACUIndex);
2670         end loop;
2671       else
2672         return;
2673       end if;
2674       /*
2675         Initialize the rule counts.  currentConditionRuleCounts is indexed by condition ID for
2676         efficiency (the alternative requires a lot more looping).
2677       */
2678       tempHighestRuleCount := 0;
2679       tempIndex := currentACUsageConditionIds.first;
2680       while(tempIndex is not null) loop
2681         tempConditionId := currentACUsageConditionIds(tempIndex);
2682         if(currentConditionRuleCounts.exists(tempConditionId)) then
2683           currentConditionRuleCounts(tempConditionId) := currentConditionRuleCounts(tempConditionId) + 1;
2684         else
2685           currentConditionRuleCounts(tempConditionId) := 1;
2686         end if;
2687         tempIndex := currentACUsageConditionIds.next(tempIndex);
2688       end loop;
2689       /* Loop through the condition usages. */
2690       while(currentACUsageConditionIds.count > 0) loop
2691         /* Set tempHighestRuleCount. */
2692         tempHighestRuleCount := 0;
2693         tempIndex := currentConditionRuleCounts.first;
2694         while(tempIndex is not null) loop
2695           if(tempHighestRuleCount < currentConditionRuleCounts(tempIndex)) then
2696             tempHighestRuleCount := currentConditionRuleCounts(tempIndex);
2697             tempConditionId := tempIndex;
2698           end if;
2699           tempIndex := currentConditionRuleCounts.next(tempIndex);
2700         end loop;
2701         /* Clear the pending-rule list. */
2702         tempPendingRuleIds.delete;
2703         /*
2704           Choose the first condition with a maximal rule count.  Recall that
2705           currentConditionRuleCounts is indexed by condition ID.
2706         */
2707     /* Following while loop commented asper Issue 14 Please refer the        */
2708     /* comments in doWeakHeaderEvaluation                                    */
2709     /*  tempConditionId := currentConditionRuleCounts.first;
2710         while(tempConditionId is not null) loop
2711           if(currentConditionRuleCounts(tempConditionId) = tempHighestRuleCount) then
2712             exit;
2713           end if;
2714           tempConditionId := currentConditionRuleCounts.next(tempConditionId);
2715         end loop;  */
2716         /* From now on, tempConditionId is the ID of the chosen condition with maximal rule count. */
2717         /* Delete this condition from currentConditionRuleCounts. */
2718         currentConditionRuleCounts.delete(tempConditionId);
2719         /*
2720           Evaluate the chosen condition.  Note that whether or not the condition is satisfied, the
2721           code first loops through the currentAC variables, locating each currentAC instance matching
2722           the chosen condition.  The code avoids compressing the two cases' loops into a single loop
2723           to avoid repeatedly branching on a boolean variable inside the loops, for efficiency.
2724         */
2725         if(conditionIsSatisfied(conditionIdIn => tempConditionId,
2726                                 itemClassIdIn => itemClassIdIn,
2727                                 itemIndexIn => itemIndexIn)) then
2728           /*
2729             Remove all usages of this condition from the current condition-usage list, adding their
2730             rules to the pending-rule list.  tempIndex indexes the next currentAC variables.
2731             tempIndex2 indexes the current currentAC variables, which may be deleted.  tempIndex3
2732             indexes tempPendingRuleIds.
2733           */
2734           tempIndex := currentACUsageConditionIds.first;
2735           tempIndex3 := 0; /* pre-increment */
2736           while(tempIndex is not null) loop
2737             tempIndex2 := tempIndex;
2738             tempIndex := currentACUsageConditionIds.next(tempIndex);
2739             if(currentACUsageConditionIds(tempIndex2) = tempConditionId) then
2740               tempIndex3 := tempIndex3 + 1;
2741               tempPendingRuleIds(tempIndex3) := currentACUsageRuleIds(tempIndex2);
2742               currentACUsageConditionIds.delete(tempIndex2);
2743               currentACUsageRuleIds.delete(tempIndex2);
2744             end if;
2745           end loop;
2746           /* If a pending rule has no other usages, add it to the applicable-rules list. */
2747           for pendingRuleIndex in 1 .. tempPendingRuleIds.count loop
2748             tempRuleApplies := true;
2749             tempIndex := currentACUsageConditionIds.first;
2750             while(tempIndex is not null) loop
2751               if(currentACUsageRuleIds(tempIndex) = tempPendingRuleIds(pendingRuleIndex)) then
2752                 tempRuleApplies := false;
2753                 exit;
2754               end if;
2755               tempIndex := currentACUsageConditionIds.next(tempIndex);
2756             end loop;
2757             if(tempRuleApplies) then
2758               tempIndex2 := engAppRuleIds.count + 1;
2759               tempRuleId := tempPendingRuleIds(pendingRuleIndex);
2760               engAppRuleIds(tempIndex2) := tempRuleId;
2761               engAppRuleTypes(tempIndex2) := engACUsageRuleTypes(tempRuleId);
2762               engRuleAppliedYN(tempIndex2) := ame_util.booleanTrue;
2763               engAppPriorities(tempIndex2) := engACUsageRulePriorities(tempRuleId);
2764               engAppApproverCategories(tempIndex2) := engACUsageRuleApprCategories(tempRuleId);
2765               engAppItemClassIds(tempIndex2) := itemClassIdIn;
2766               engAppItemIds(tempIndex2) := engItemIds(itemIndexIn);
2767               /*
2768                 doPerItemRuleEvaluation only evaluates subordinate-item-class rules, so here
2769                   engAppRuleItemClassIds(i) = engAppItemClassIds(i) and
2770                   engAppAppItemIds(i) = engAppItemIds(i)
2771                 always.
2772               */
2773               engAppRuleItemClassIds(tempIndex2) := itemClassIdIn;
2774               engAppAppItemIds(tempIndex2) := engItemIds(itemIndexIn);
2775             end if;
2776           end loop;
2777         else /* The condition is not satisfied. */
2778           /* Find all rules using the chosen condition. */
2779           tempIndex := currentACUsageConditionIds.first;
2780           tempIndex2 := 0; /* tempIndex2 indexes tempPendingRuleIds; pre-increment it. */
2781           while(tempIndex is not null) loop
2782             if(currentACUsageConditionIds(tempIndex) = tempConditionId) then
2783               tempIndex2 := tempIndex2 + 1;
2784               tempPendingRuleIds(tempIndex2) := currentACUsageRuleIds(tempIndex);
2785             end if;
2786             tempIndex := currentACUsageConditionIds.next(tempIndex);
2787           end loop;
2788           /*
2789             Remove all usages for rules using the chosen condition.  If the usage is for
2790             a condition other than the chosen condition, decrement that condition's
2791             rule count.  Here tempIndex indexes the next currentAC variable; tempIndex2
2792             indexes the current currentAC variable, which may be deleted; and tempIndex3
2793             indexes the engApp variables.
2794           */
2795           for pendingRuleIndex in 1 .. tempPendingRuleIds.count loop
2796             tempIndex := currentACUsageConditionIds.first;
2797             while(tempIndex is not null) loop
2798               tempIndex2 := tempIndex;
2799               tempIndex := currentACUsageConditionIds.next(tempIndex);
2800               if(currentACUsageRuleIds(tempIndex2) = tempPendingRuleIds(pendingRuleIndex)) then
2801                 tempConditionId2 := currentACUsageConditionIds(tempIndex2);
2802                 if(tempConditionId2 <> tempConditionId) then
2803                   currentConditionRuleCounts(tempConditionId2) := currentConditionRuleCounts(tempConditionId2) - 1;
2804                 end if;
2805                 currentACUsageConditionIds.delete(tempIndex2);
2806                 currentACUsageRuleIds.delete(tempIndex2);
2807               end if;
2808             end loop;
2809           end loop;
2810         end if;
2811       end loop;
2812       exception
2813         when others then
2814           ame_util.runtimeException(packageNameIn => 'ame_engine',
2815                                     routineNameIn => 'doPerItemRuleEvaluation',
2816                                     exceptionNumberIn => sqlcode,
2817                                     exceptionStringIn => sqlerrm);
2818           raise;
2819     end doPerItemRuleEvaluation;
2820   procedure doStrictHeaderRuleEvaluation(itemClassIndexIn in integer,
2821                                          itemClassIdIn in integer) as
2822     currentACUsageConditionIds ame_util.idList;
2823     currentACUsageRuleIds ame_util.idList;
2824     headerItemIndex integer;
2825     tempFirstRuleIndex integer;
2826     tempLastRuleIndex integer;
2827     tempIndex integer;
2828     tempIndex2 integer;
2829     tempItemClassId integer;
2830     tempItemClassIndex integer;
2831     tempItemId ame_util.stringType;
2832     tempLowerLimit integer;
2833     tempRuleApplies boolean;
2834     tempRuleId integer;
2835     tempRuleId2 integer;
2836     tempUpperLimit integer;
2837     begin
2838       /* Handle the null case (no active conditions) first. */
2839       if(not engACUsageFirstIndexes.exists(itemClassIdIn)) then
2840         return;
2841       end if;
2842       /*
2843         A header-level rule can have conditions on attributes of at most one subordinate
2844         item class.  The active condition usages are sorted first by item class, then
2845         by rule ID; so within this procedure, the header item class' active condition
2846         usages are sorted by rule ID.  This procedure therefore loops through the rules
2847         in the active condition usages one rule at a time.  For each rule, if any of the
2848         conditions is defined on an attribute of a subordinate item class, the procedure
2849         loops through the items of that class, looking for an item that satisfies all of
2850         the rule's subordinate-item-level conditions.
2851       */
2852       /* Initialize the current condition usages. */
2853       tempIndex := 0; /* pre-increment */
2854       for ACUIndex in
2855         engACUsageFirstIndexes(itemClassIdIn) ..
2856         (engACUsageFirstIndexes(itemClassIdIn) + engACUsageItemClassCounts(itemClassIdIn) - 1) loop
2857         tempIndex := tempIndex + 1;
2858         currentACUsageConditionIds(tempIndex) := engACUsageConditionIds(ACUIndex);
2859         currentACUsageRuleIds(tempIndex) := engACUsageRuleIds(ACUIndex);
2860       end loop;
2861       if(currentACUsageRuleIds.count = 0) then
2862         /* There are no condition usages to process, so just return. */
2863         return;
2864       end if;
2865       headerItemIndex := engItemClassItemIdIndexes(itemClassIndexIn);
2866       tempFirstRuleIndex := 1;
2867       /* The following value of tempIndex is used throughout the remainder of the code; don't change it. */
2868       tempIndex := currentACUsageRuleIds.count;
2869       while(tempFirstRuleIndex is not null) loop
2870         tempRuleId := currentACUsageRuleIds(tempFirstRuleIndex);
2871         /* Find the last current condition usage with the rule ID tempRuleId. */
2872         tempLastRuleIndex := tempFirstRuleIndex;
2873         while(tempLastRuleIndex < tempIndex and
2874               currentACUsageRuleIds(tempLastRuleIndex + 1) = tempRuleId) loop
2875           tempLastRuleIndex := tempLastRuleIndex + 1;
2876         end loop;
2877         /*
2878           Determine whether the current rule references any conditions on attributes belonging
2879           to a subordinate item class.  If so, all such conditions are on the same item class,
2880           and tempItemClassId is its index.  Otherwise, tempItemClassId identifies the header
2881           item class, and tempItemId identifies the header item.
2882         */
2883         tempItemClassId := itemClassIdIn;
2884         tempItemId := engTransactionId;
2885         for ruleIndex in tempFirstRuleIndex .. tempLastRuleIndex loop
2886           tempItemClassId := engAttributeItemClassIds(engACAttributeIds(currentACUsageConditionIds(ruleIndex)));
2887           if(tempItemClassId <> itemClassIdIn) then
2888             exit;
2889           end if;
2890         end loop;
2891         tempRuleApplies := true;
2892         /* First loop through the header-level conditions. */
2893         for ruleIndex in tempFirstRuleIndex .. tempLastRuleIndex loop
2894           if(engAttributeItemClassIds(engACAttributeIds(currentACUsageConditionIds(ruleIndex))) = itemClassIdIn and
2895              not conditionIsSatisfied(conditionIdIn => currentACUsageConditionIds(ruleIndex),
2896                                       itemClassIdIn => itemClassIdIn,
2897                                       itemIndexIn   => headerItemIndex)) then
2898             tempRuleApplies := false;
2899             exit;
2900           end if;
2901         end loop;
2902         /*
2903           If the rule still applies and at least one condition is defined on a subordinate-item-level
2904           attribute, loop through the subordinate items, looking for an item that satisfies all of the
2905           rule's subordinate-item-level conditions.
2906         */
2907         if(tempRuleApplies and
2908            tempItemClassId <> itemClassIdIn) then
2909           tempItemClassIndex := engItemClassIndexes(tempItemClassId);
2910           tempLowerLimit := engItemClassItemIdIndexes(tempItemClassIndex);
2911           tempRuleApplies := false;
2912           /*
2913             If tempLowerLimit is null, no items exist in this item class, so the rule's conditions
2914             on attributes defined on the item class cannot be satisfied.  In this case, tempRuleApplies
2915             stays false.
2916           */
2917           if(tempLowerLimit is not null) then
2918             tempUpperLimit := (engItemClassItemIdIndexes(tempItemClassIndex) + engItemCounts(tempItemClassIndex) - 1);
2919             for itemIndex in tempLowerLimit .. tempUpperLimit loop
2920               for ruleIndex in tempFirstRuleIndex .. tempLastRuleIndex loop
2921                 if(engAttributeItemClassIds(engACAttributeIds(currentACUsageConditionIds(ruleIndex))) =
2922                      tempItemClassId) then
2923                   if(conditionIsSatisfied(conditionIdIn => currentACUsageConditionIds(ruleIndex),
2924                                           itemClassIdIn => tempItemClassId,
2925                                           itemIndexIn => itemIndex)) then
2926                     /* The rule is only satisfied if all the conditions have succeeded. */
2927                     if(ruleIndex = tempLastRuleIndex) then
2928                       tempRuleApplies := true;
2929                       tempItemId := engItemIds(itemIndex);
2930                       exit;
2931                     end if;
2932                   else
2933                     /*
2934                       The condition is not satisfied, so the current item does not satisfy the rule.
2935                       Leave tempRuleApplies false and exit the inner loop.
2936                     */
2937                     exit;
2938                   end if;
2939                 end if;
2940               end loop;
2941               if(tempRuleApplies) then
2942                 exit;
2943               end if;
2944             end loop;
2945           end if;
2946         end if;
2947         /* If the rule applies, write it to the applicable-rule package variables. */
2948         if(tempRuleApplies) then
2949           tempIndex2 := engAppRuleIds.count + 1;
2950           tempRuleId2 := currentACUsageRuleIds(tempFirstRuleIndex);
2951           engAppRuleIds(tempIndex2) := tempRuleId2;
2952           engAppRuleTypes(tempIndex2) := engACUsageRuleTypes(tempRuleId2);
2953           engRuleAppliedYN(tempIndex2) := ame_util.booleanTrue;
2954           engAppPriorities(tempIndex2) := engACUsageRulePriorities(tempRuleId2);
2955           engAppApproverCategories(tempIndex2) := engACUsageRuleApprCategories(tempRuleId2);
2956           /* These two variables indicate which item satisfied the rule. */
2957           engAppItemClassIds(tempIndex2) := tempItemClassId;
2958           engAppItemIds(tempIndex2) := tempItemId;
2959           /* These two variables indicate which item the rule applies to, i.e. the header item. */
2960           engAppRuleItemClassIds(tempIndex2) := itemClassIdIn;
2961           engAppAppItemIds(tempIndex2) := engTransactionId;
2962         end if;
2963         /* Iterate or exit the main loop. */
2964         if(tempLastRuleIndex < tempIndex) then
2965           tempFirstRuleIndex := tempLastRuleIndex + 1;
2966         else
2967           exit;
2968         end if;
2969       end loop;
2970       exception
2971         when others then
2972           ame_util.runtimeException(packageNameIn => 'ame_engine',
2973                                     routineNameIn => 'doStrictHeaderRuleEvaluation',
2974                                     exceptionNumberIn => sqlcode,
2975                                     exceptionStringIn => sqlerrm);
2976           raise;
2977     end doStrictHeaderRuleEvaluation;
2978   procedure doWeakHeaderRuleEvaluation(itemClassIndexIn in integer,
2979                                        itemClassIdIn in integer) as
2980     currentACUsageConditionIds ame_util.idList;
2981     currentACUsageRuleIds ame_util.idList;
2982     currentConditionRuleCounts ame_util.idList;
2983     tempAttributeItemClassIndex integer;
2984     tempConditionId integer;
2985     tempConditionId2 integer;
2986     tempConditionIsSatisfied boolean;
2987     tempHighestRuleCount integer;
2988     tempIndex integer;
2989     tempIndex2 integer;
2990     tempIndex3 integer;
2991     tempLowerLimit integer;
2992     tempPendingRuleIds ame_util.idList;
2993     tempRuleApplies boolean;
2994     tempRuleId integer;
2995     tempUpperLimit integer;
2996     begin
2997       /* Handle the null case (no active conditions) first. */
2998       if(not engACUsageFirstIndexes.exists(itemClassIdIn)) then
2999         return;
3000       end if;
3001       /*
3002         Initialize the current condition usages.  Note that while the currentACUsage local
3003         variables start out as compact lists, the algorithm that iterates through them
3004         deletes them in an unpredictable order, and does not re-compact the lists; so the
3005         algorithm must treat these lists as sparse.
3006       */
3007       tempIndex := 0; /* pre-increment */
3008       for ACUIndex in
3009         engACUsageFirstIndexes(itemClassIdIn) ..
3010         (engACUsageFirstIndexes(itemClassIdIn) + engACUsageItemClassCounts(itemClassIdIn) - 1) loop
3011         tempIndex := tempIndex + 1;
3012         currentACUsageConditionIds(tempIndex) := engACUsageConditionIds(ACUIndex);
3013         currentACUsageRuleIds(tempIndex) := engACUsageRuleIds(ACUIndex);
3014       end loop;
3015       /*
3016         Initialize the rule counts.  currentConditionRuleCounts is indexed by condition ID for
3017         efficiency (the alternative requires a lot more looping).
3018       */
3019       tempIndex := currentACUsageConditionIds.first;
3020       while(tempIndex is not null) loop
3021         tempConditionId := currentACUsageConditionIds(tempIndex);
3022         if(currentConditionRuleCounts.exists(tempConditionId)) then
3023           currentConditionRuleCounts(tempConditionId) := currentConditionRuleCounts(tempConditionId) + 1;
3024         else
3025           currentConditionRuleCounts(tempConditionId) := 1;
3026         end if;
3027         tempIndex := currentACUsageConditionIds.next(tempIndex);
3028       end loop;
3029       /* Loop through the condition usages. */
3030       while(currentACUsageConditionIds.count > 0) loop
3031         /* Set tempHighestRuleCount. */
3032         tempHighestRuleCount := 0;
3033         tempIndex := currentConditionRuleCounts.first;
3034         while(tempIndex is not null) loop
3035           if(tempHighestRuleCount < currentConditionRuleCounts(tempIndex)) then
3036             tempHighestRuleCount := currentConditionRuleCounts(tempIndex);
3037     /* Following line has been added to avoid the another while loop to      */
3038     /* find the condition with highest rule count. Issue 14 of the bug list  */
3039     /* No bug logged for this                                                */
3040     /* currentConditionRuleCounts is pl/sql list which is sparse and indexes */
3041     /* are nothig but condition_ids.Hence there is no need to find the       */
3042     /* condition_id which has highestRuleCount in another loop.after this    */
3043     /* while loop the tempConditionId is the condition with highestRuleCount.*/
3044             tempConditionId := tempIndex;
3045           end if;
3046           tempIndex := currentConditionRuleCounts.next(tempIndex);
3047         end loop;
3048         /* Clear the pending-rule list. */
3049         tempPendingRuleIds.delete;
3050         /*
3051           Choose the first condition with a maximal rule count.  Recall that currentConditionRuleCounts
3052           is indexed by condition ID.
3053         */
3054     /* Removing this while loop as we already know the condition with        */
3055     /* highest rule count                                                    */
3056     /*  tempConditionId := currentConditionRuleCounts.first;
3057         while(tempConditionId is not null) loop
3058           if(currentConditionRuleCounts(tempConditionId) = tempHighestRuleCount) then
3059             exit;
3060           end if;
3061           tempConditionId := currentConditionRuleCounts.next(tempConditionId);
3062         end loop;*/
3063         /* From now on, tempConditionId is the ID of the chosen condition with maximal rule count. */
3064         /* Delete this condition from currentConditionRuleCounts. */
3065         currentConditionRuleCounts.delete(tempConditionId);
3066         /*
3067           Test the condition for each item in the item class of the attribute on which the condition
3068           is defined, until an item satisfies the condition or no items are left.
3069         */
3070         tempAttributeItemClassIndex :=
3071           engItemClassIndexes(engAttributeItemClassIds(engACAttributeIds(tempConditionId)));
3072         tempConditionIsSatisfied := false;
3073         tempLowerLimit := engItemClassItemIdIndexes(tempAttributeItemClassIndex);
3074         if(tempLowerLimit is not null) then
3075           tempUpperLimit :=
3076             (engItemClassItemIdIndexes(tempAttributeItemClassIndex) + engItemCounts(tempAttributeItemClassIndex) - 1);
3077           for itemIndex in tempLowerLimit .. tempUpperLimit loop
3078             if(conditionIsSatisfied(conditionIdIn => tempConditionId,
3079                                     itemClassIdIn => engAttributeItemClassIds(engACAttributeIds(tempConditionId)),
3080                                     itemIndexIn   => itemIndex)) then
3081               tempConditionIsSatisfied := true;
3082               exit;
3083             end if;
3084           end loop;
3085         end if;
3086         /*
3087           If the condition is satisfied, eliminate its usages, and add any rules with no other
3088           usages to the applicable-rules list.  If the condition is not satisfied, just eliminate
3089           its usages, and any other usages for the rules in the condition's usages.
3090         */
3091         if(tempConditionIsSatisfied) then
3092           /*
3093             Remove all usages of this condition from the current condition-usage list, adding their
3094             rules to the pending-rule list.  tempIndex indexes the next currentAC variables.
3095             tempIndex2 indexes the current currentAC variables, which may be deleted.  tempIndex3
3096             indexes tempPendingRuleIds.
3097           */
3098           tempIndex := currentACUsageConditionIds.first;
3099           tempIndex3 := 0; /* pre-increment */
3100           while(tempIndex is not null) loop
3101             tempIndex2 := tempIndex;
3102             tempIndex := currentACUsageConditionIds.next(tempIndex);
3103             if(currentACUsageConditionIds(tempIndex2) = tempConditionId) then
3104               tempIndex3 := tempIndex3 + 1;
3105               tempPendingRuleIds(tempIndex3) := currentACUsageRuleIds(tempIndex2);
3106               currentACUsageConditionIds.delete(tempIndex2);
3107               currentACUsageRuleIds.delete(tempIndex2);
3108             end if;
3109           end loop;
3110           /* If a pending rule has no other usages, add it to the applicable-rules list. */
3111           for pendingRuleIndex in 1 .. tempPendingRuleIds.count loop
3112             tempRuleApplies := true;
3113             tempIndex := currentACUsageConditionIds.first;
3114             while(tempIndex is not null) loop
3115               if(currentACUsageRuleIds(tempIndex) = tempPendingRuleIds(pendingRuleIndex)) then
3116                 tempRuleApplies := false;
3117                 exit;
3118               end if;
3119               tempIndex := currentACUsageConditionIds.next(tempIndex);
3120             end loop;
3121             if(tempRuleApplies) then
3122               tempIndex2 := engAppRuleIds.count + 1;
3123               tempRuleId := tempPendingRuleIds(pendingRuleIndex);
3124               engAppRuleIds(tempIndex2) := tempRuleId;
3125               engAppRuleTypes(tempIndex2) := engACUsageRuleTypes(tempRuleId);
3126               engRuleAppliedYN(tempIndex2) := ame_util.booleanTrue;
3127               engAppPriorities(tempIndex2) := engACUsageRulePriorities(tempRuleId);
3128               engAppApproverCategories(tempIndex2) := engACUsageRuleApprCategories(tempRuleId);
3129               engAppItemClassIds(tempIndex2) := itemClassIdIn;
3130               engAppItemIds(tempIndex2) := engTransactionId;
3131               /* In this case the satisfying item and item to which the rule applies always match. */
3132               engAppRuleItemClassIds(tempIndex2) := engAppItemClassIds(tempIndex2);
3133               engAppAppItemIds(tempIndex2) := engAppItemIds(tempIndex2);
3134             end if;
3135           end loop;
3136         else /* The condition is not satisfied. */
3137           /* Put all rules using the chosen condition in the pending-rule list. */
3138           tempIndex := currentACUsageConditionIds.first;
3139           tempIndex2 := 0; /* tempIndex2 indexes tempPendingRuleIds; pre-increment it. */
3140           while(tempIndex is not null) loop
3141             if(currentACUsageConditionIds(tempIndex) = tempConditionId) then
3142               tempIndex2 := tempIndex2 + 1;
3143               tempPendingRuleIds(tempIndex2) := currentACUsageRuleIds(tempIndex);
3144             end if;
3145             tempIndex := currentACUsageConditionIds.next(tempIndex);
3146           end loop;
3147           /*
3148             Remove all usages for rules using the chosen condition.  If the usage is for
3149             a condition other than the chosen condition, decrement that condition's
3150             rule count.  Here tempIndex indexes the next currentAC variable, and tempIndex2
3151             indexes the current currentAC variable (which may be deleted).
3152           */
3153           for pendingRuleIndex in 1 .. tempPendingRuleIds.count loop
3154             tempIndex := currentACUsageConditionIds.first;
3155             while(tempIndex is not null) loop
3156               tempIndex2 := tempIndex;
3157               tempIndex := currentACUsageConditionIds.next(tempIndex);
3158               if(currentACUsageRuleIds(tempIndex2) = tempPendingRuleIds(pendingRuleIndex)) then
3159                 tempConditionId2 := currentACUsageConditionIds(tempIndex2);
3160                 if(tempConditionId2 <> tempConditionId) then
3161                   currentConditionRuleCounts(tempConditionId2) := currentConditionRuleCounts(tempConditionId2) - 1;
3162                 end if;
3163                 currentACUsageConditionIds.delete(tempIndex2);
3164                 currentACUsageRuleIds.delete(tempIndex2);
3165               end if;
3166             end loop;
3167           end loop;
3168         end if;
3169       end loop;
3170       exception
3171         when others then
3172           ame_util.runtimeException(packageNameIn => 'ame_engine',
3173                                     routineNameIn => 'doWeakHeaderRuleEvaluation',
3174                                     exceptionNumberIn => sqlcode,
3175                                     exceptionStringIn => sqlerrm);
3176           raise;
3177     end doWeakHeaderRuleEvaluation;
3178   procedure evaluateRules as
3179     /*
3180       conditionlessRuleCursor finds all rules having no ordinary or exception conditions
3181       that the current transaction type uses.
3182     */
3183     cursor conditionlessRuleCursor(processPrioritiesIn in varchar2,
3184                                    processProductionRulesIn in varchar2,
3185                                    combinationRulePriorityModeIn in varchar2,
3186                                    combinationRuleThresholdIn in integer,
3187                                    authorityRulePriorityModeIn in varchar2,
3188                                    authorityRuleThresholdIn in integer,
3189                                    exceptionRulePriorityModeIn in varchar2,
3190                                    exceptionRuleThresholdIn in integer,
3191                                    listModRulePriorityModeIn in varchar2,
3192                                    listModRuleThresholdIn in integer,
3193                                    substRulePriorityModeIn in varchar2,
3194                                    substRuleThresholdIn in integer,
3195                                    preRulePriorityModeIn in varchar2,
3196                                    preRuleThresholdIn in integer,
3197                                    postRulePriorityModeIn in varchar2,
3198                                    postRuleThresholdIn in integer,
3199                                    productionRulePriorityModeIn in varchar2,
3200                                    productionRuleThresholdIn in integer,
3201                                    headerItemClassIdIn in integer) is
3202       select
3203         ame_rules.rule_id rule_id,
3204         nvl(ame_rules.item_class_id,
3205             headerItemClassIdIn) item_class_id,
3206         ame_rules.rule_type rule_type,
3207         ame_rule_usages.priority priority,
3208         ame_rule_usages.approver_category approver_category
3209       from
3210         ame_rules,
3211         ame_rule_usages,
3212         ame_item_class_usages
3213       where
3214         ame_rules.rule_id = ame_rule_usages.rule_id and
3215         ame_rule_usages.item_id = engAmeApplicationId and
3216         nvl(ame_rules.item_class_id, headerItemClassIdIn) = ame_item_class_usages.item_class_id and
3217         ame_item_class_usages.application_id = engAmeApplicationId and
3218         (processPrioritiesIn = ame_util.booleanFalse or
3219          (ame_rules.rule_type = ame_util.combinationRuleType and
3220           (combinationRulePriorityModeIn <> ame_util.absoluteRulePriority or
3221            combinationRuleThresholdIn >= ame_rule_usages.priority)) or
3222          (ame_rules.rule_type = ame_util.authorityRuleType and
3223           (authorityRulePriorityModeIn <> ame_util.absoluteRulePriority or
3224            authorityRuleThresholdIn >= ame_rule_usages.priority)) or
3225          (ame_rules.rule_type = ame_util.exceptionRuleType and
3226           (exceptionRulePriorityModeIn <> ame_util.absoluteRulePriority or
3227            exceptionRuleThresholdIn >= ame_rule_usages.priority)) or
3228          (ame_rules.rule_type = ame_util.listModRuleType and
3229           (listModRulePriorityModeIn <> ame_util.absoluteRulePriority or
3230            listModRuleThresholdIn >= ame_rule_usages.priority)) or
3231          (ame_rules.rule_type = ame_util.substitutionRuleType and
3232           (substRulePriorityModeIn <> ame_util.absoluteRulePriority or
3233            substRuleThresholdIn >= ame_rule_usages.priority)) or
3234          (ame_rules.rule_type = ame_util.preListGroupRuleType and
3235           (preRulePriorityModeIn <> ame_util.absoluteRulePriority or
3236            preRuleThresholdIn >= ame_rule_usages.priority)) or
3237          (ame_rules.rule_type = ame_util.postListGroupRuleType and
3238           (postRulePriorityModeIn <> ame_util.absoluteRulePriority or
3239            postRuleThresholdIn >= ame_rule_usages.priority)) or
3240          (ame_rules.rule_type = ame_util.productionRuleType and
3241           (productionRulePriorityModeIn <> ame_util.absoluteRulePriority or
3242            productionRuleThresholdIn >= ame_rule_usages.priority))) and
3243         (processProductionRulesIn = ame_util.booleanTrue or
3244          ame_rules.rule_type <> ame_util.productionRuleType) and
3245         not exists (select *
3246                       from
3247                         ame_conditions,
3248                         ame_condition_usages
3249                       where
3250                         ame_conditions.condition_type <> ame_util.listModConditionType and
3251                         ame_conditions.condition_id = ame_condition_usages.condition_id and
3252                         ame_condition_usages.rule_id = ame_rules.rule_id and
3253                         engEffectiveRuleDate between
3254                           ame_conditions.start_date and
3255                           nvl(ame_conditions.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3256                         engEffectiveRuleDate between
3257                           ame_condition_usages.start_date and
3258                           nvl(ame_condition_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3259                         /* Avoids second fetch otherwise required by ANSI standard to check for too many rows. */
3260                         rownum < 2) and
3261         engEffectiveRuleDate between
3262           ame_rules.start_date and
3263           nvl(ame_rules.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3264         engEffectiveRuleDate between
3265           ame_rule_usages.start_date and
3266           nvl(ame_rule_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3267         engEffectiveRuleDate between
3268           ame_item_class_usages.start_date and
3269           nvl(ame_item_class_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate)
3270       order by
3271         ame_item_class_usages.item_class_order_number,
3272         item_class_id,
3273         ame_rules.rule_type,
3274         ame_rules.rule_id;
3275     conditionlessItemClassIds ame_util.idList;
3276     conditionlessRuleApprCats ame_util.charList;
3277     conditionlessRuleIds ame_util.idList;
3278     conditionlessRulePriorities ame_util.idList;
3279     conditionlessRuleTypes ame_util.stringList;
3280     errorCode integer;
3281     errorMessage ame_util.longestStringType;
3282     firstConditionlessRuleFound boolean;
3283     firstConditionlessRuleIndex integer;
3284     lastConditionlessRuleIndex integer;
3285     lowerBound integer;
3286     noRulesException exception;
3287     processPriorities ame_util.charType;
3288     processProductions ame_util.charType;
3289     tempIndex integer;
3290     tempItemClassId integer;
3291     upperBound integer;
3292     upperBound2 integer;
3293     begin
3294       /* Fetch all conditionless rules and store them in local variables. */
3295       if(engProcessPriorities) then
3296         processPriorities := ame_util.booleanTrue;
3297       else
3298         processPriorities := ame_util.booleanFalse;
3299       end if;
3300       if(engProcessProductionRules) then
3301         processProductions := ame_util.booleanTrue;
3302       else
3303         processProductions := ame_util.booleanFalse;
3304       end if;
3305       open conditionlessRuleCursor(processPrioritiesIn => processPriorities,
3306                                    processProductionRulesIn => processProductions,
3307                                    combinationRulePriorityModeIn => engPriorityModes(ame_util.combinationRuleType),
3308                                    combinationRuleThresholdIn => engPriorityThresholds(ame_util.combinationRuleType),
3309                                    authorityRulePriorityModeIn => engPriorityModes(ame_util.authorityRuleType),
3310                                    authorityRuleThresholdIn => engPriorityThresholds(ame_util.authorityRuleType),
3311                                    exceptionRulePriorityModeIn => engPriorityModes(ame_util.exceptionRuleType),
3312                                    exceptionRuleThresholdIn => engPriorityThresholds(ame_util.exceptionRuleType),
3313                                    listModRulePriorityModeIn => engPriorityModes(ame_util.listModRuleType),
3314                                    listModRuleThresholdIn => engPriorityThresholds(ame_util.listModRuleType),
3315                                    substRulePriorityModeIn => engPriorityModes(ame_util.substitutionRuleType),
3316                                    substRuleThresholdIn => engPriorityThresholds(ame_util.substitutionRuleType),
3317                                    preRulePriorityModeIn => engPriorityModes(ame_util.preListGroupRuleType),
3318                                    preRuleThresholdIn => engPriorityThresholds(ame_util.preListGroupRuleType),
3319                                    postRulePriorityModeIn => engPriorityModes(ame_util.postListGroupRuleType),
3320                                    postRuleThresholdIn => engPriorityThresholds(ame_util.postListGroupRuleType),
3321                                    productionRulePriorityModeIn => engPriorityModes(ame_util.productionRuleType),
3322                                    productionRuleThresholdIn => engPriorityThresholds(ame_util.productionRuleType),
3323                                    headerItemClassIdIn => getItemClassId(itemClassNameIn => ame_util.headerItemClassName));
3324       fetch conditionlessRuleCursor bulk collect
3325         into
3326           conditionlessRuleIds,
3327           conditionlessItemClassIds,
3328           conditionlessRuleTypes,
3329           conditionlessRulePriorities,
3330           conditionlessRuleApprCats;
3331       close conditionlessRuleCursor;
3332       firstConditionlessRuleIndex := 0;
3333       lastConditionlessRuleIndex := 0;
3334       /*
3335         Loop through the item classes in engItemClassIds, evaluating the
3336         transaction type's rules for each item in each class.
3337       */
3338       for itemClassIndex in 1 .. engItemClassIds.count loop
3339         lowerBound := engItemClassItemIdIndexes(itemClassIndex);
3340         if(lowerBound is not null) then
3341           upperBound := engItemClassItemIdIndexes(itemClassIndex) + engItemCounts(itemClassIndex) - 1;
3342           tempItemClassId := engItemClassIds(itemClassIndex);
3343           /* Find this item class' conditionless rules. */
3344           firstConditionlessRuleFound := false;
3345           upperBound2 := conditionlessRuleIds.count;
3346           /* Following for loop modified for bug 4094058 Issue 19 */
3347           for i in firstConditionlessRuleIndex + 1 .. upperBound2 loop
3348             if(firstConditionlessRuleFound) then
3349               if(conditionlessItemClassIds(i) = tempItemClassId) then
3350                 lastConditionlessRuleIndex := i;
3351               end if;
3352             else
3353               if(conditionlessItemClassIds(i) = tempItemClassId) then
3354                 firstConditionlessRuleFound := true;
3355                 firstConditionlessRuleIndex := i;
3356                 lastConditionlessRuleIndex := i;
3357               end if;
3358             end if;
3359             if (i < upperBound2 and conditionlessItemClassIds(i+1) <> tempItemClassId) then
3360               exit;
3361             end if;
3362           end loop;
3363           /* Loop through the items in this item class. */
3364           for itemIndex in lowerBound .. upperBound loop
3365             /* Add any conditionless rules for the current item class to the current item's applicable-rule list. */
3366             if(firstConditionlessRuleFound) then
3367               tempIndex := engAppRuleIds.count; /* pre-increment */
3368               for conditionlessRuleIndex in firstConditionlessRuleIndex .. lastConditionlessRuleIndex loop
3369                 tempIndex := tempIndex + 1;
3370                 engAppRuleIds(tempIndex) := conditionlessRuleIds(conditionlessRuleIndex);
3371                 engAppPriorities(tempIndex) := conditionlessRulePriorities(conditionlessRuleIndex);
3372                 engAppApproverCategories(tempIndex) := conditionlessRuleApprCats(conditionlessRuleIndex);
3373                 engAppRuleTypes(tempIndex) := conditionlessRuleTypes(conditionlessRuleIndex);
3374                 engRuleAppliedYN(tempIndex) := ame_util.booleanTrue;
3375                 /* These are the item class and item to which the rule applies. */
3376                 engAppItemClassIds(tempIndex) := tempItemClassId;
3377                 engAppItemIds(tempIndex) := engItemIds(itemIndex);
3378                 /*
3379                   These are the item class and item that satisfy the rule.  By convention, for rules
3380                   having no ordinary conditions, these are the same as the item class and item to
3381                   which the rule applies.
3382                 */
3383                 engAppRuleItemClassIds(tempIndex) := tempItemClassId;
3384                 engAppAppItemIds(tempIndex) := engItemIds(itemIndex);
3385               end loop;
3386             end if;
3387             /* Evaluate the rules with conditions for this item. */
3388             if(engItemClassNames(itemClassIndex) = ame_util.headerItemClassName) then
3389               /*
3390                 The header item class always has exactly one item, so one of the procedures
3391                 in the following if/else will get called exactly once per engine cycle.
3392               */
3393               if(getHeaderAttValue2(attributeNameIn => ame_util.restrictiveItemEvalAttribute) =
3394                  ame_util.booleanAttributeTrue) then
3395                 doStrictHeaderRuleEvaluation(itemClassIndexIn => itemClassIndex,
3396                                              itemClassIdIn => tempItemClassId);
3397               else
3398                 doWeakHeaderRuleEvaluation(itemClassIndexIn => itemClassIndex,
3399                                            itemClassIdIn => tempItemClassId);
3400               end if;
3401             else
3402               /* Evaluate the rules in the active conditions for the current item only. */
3403               doPerItemRuleEvaluation(itemClassIdIn => tempItemClassId,
3404                                       itemIndexIn => itemIndex);
3405             end if;
3406           end loop;
3407         end if;
3408       end loop;
3409       /*
3410         So far, list-modification and substitution rules have been treated as if they belonged
3411         to the header item class.  Now set their item-class IDs and item IDs null and sort the
3412         applicable rules, so the list-modification and substitution rules get processed last.
3413       */
3414       for i in 1 .. engAppRuleIds.count loop
3415         if(engAppRuleTypes(i) in (ame_util.listModRuleType, ame_util.substitutionRuleType)) then
3416           engRuleAppliedYN(i) := ame_util.booleanFalse;
3417           engAppLMSubItemClassIds(engAppRuleIds(i)) := engAppRuleItemClassIds(i);
3418           engAppLMSubItemIds(engAppRuleIds(i)) := engAppAppItemIds(i);
3419           engAppRuleItemClassIds(i) := null;
3420           engAppAppItemIds(i) := null;
3421         end if;
3422       end loop;
3423       sortApplicableRules(sortByActionTypeIn => false);
3424       /*
3425         Priority processing has so far occurred only for absolute priorities--for conditionless
3426         rules in the conditionlessRuleCursor in this procedure, for rule with conditions in the
3427         activeCondUsageCursor cursor of the procedure fetchActiveConditionUsages.  Now that the
3428         remaining applicable rules are sorted by rule type, we can process relative priorities.
3429       */
3430       if(engProcessPriorities) then
3431         processRelativePriorities;
3432       end if;
3433       if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
3434         if engAppRuleIds.count = 0 then
3435           fnd_log.string
3436             (fnd_log.level_statement
3437             ,'ame_engine.evaluateRules'
3438             ,'*********** No Rules Applicable ************'
3439             );
3440         else
3441           for i in 1 .. engAppRuleIds.count loop
3442             fnd_log.string
3443               (fnd_log.level_statement
3444               ,'ame_engine.evaluateRules'
3445               ,'Applicable Rule ::: ' || engAppRuleIds(i)
3446               );
3447           end loop;
3448         end if;
3449       end if;
3450       /* Check for no rules, if AT_LEAST_ONE_RULE_MUST_APPLY is true. */
3451       if(getHeaderAttValue2(attributeNameIn => ame_util.atLeastOneRuleAttribute) = ame_util.booleanAttributeTrue and
3452          engAppRuleIds.count = 0) then
3453         raise noRulesException;
3454       end if;
3455       exception
3456         when noRulesException then
3457           errorCode := -20001;
3458           errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
3459                                               messageNameIn => 'AME_400117_ENG_ONE_RULE_APPLY');
3460           ame_util.runtimeException(packageNameIn => 'ame_engine',
3461                                     routineNameIn => 'evaluateRules',
3462                                     exceptionNumberIn => errorCode,
3463                                     exceptionStringIn => errorMessage);
3464           raise_application_error(errorCode,
3465                                   errorMessage);
3466         when others then
3467           if(conditionlessRuleCursor%isopen) then
3468             close conditionlessRuleCursor;
3469           end if;
3470           ame_util.runtimeException(packageNameIn => 'ame_engine',
3471                                     routineNameIn => 'evaluateRules',
3472                                     exceptionNumberIn => sqlcode,
3473                                     exceptionStringIn => sqlerrm);
3474           raise;
3475     end evaluateRules;
3476   procedure fetchActiveConditionUsages as
3477     cursor activeCondStringValueCursor is
3478       select
3479         condition_id,
3480         string_value
3481       from ame_string_values
3482       where
3483         condition_id in
3484           (select ame_condition_usages.condition_id
3485             from
3486               ame_attributes,
3487               ame_conditions,
3488               ame_condition_usages,
3489               ame_rule_usages
3490             where
3491               ame_attributes.attribute_type = ame_util.stringAttributeType and
3492               ame_attributes.attribute_id = ame_conditions.attribute_id and
3493               ame_conditions.condition_id = ame_condition_usages.condition_id and
3494               ame_condition_usages.rule_id = ame_rule_usages.rule_id and
3495               ame_rule_usages.item_id = engAmeApplicationId and
3496               engEffectiveRuleDate between
3497                 ame_attributes.start_date and
3498                 nvl(ame_attributes.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3499               engEffectiveRuleDate between
3500                 ame_conditions.start_date and
3501                 nvl(ame_conditions.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3502               engEffectiveRuleDate between
3503                 ame_condition_usages.start_date and
3504                 nvl(ame_condition_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3505               engEffectiveRuleDate between
3506                 ame_rule_usages.start_date and
3507                 nvl(ame_rule_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate)) and
3508         engEffectiveRuleDate between
3509           ame_string_values.start_date and
3510           nvl(ame_string_values.end_date - ame_util.oneSecond, engEffectiveRuleDate)
3511       order by condition_id;
3512     cursor activeCondUsageCursor(processPrioritiesIn in varchar2,
3513                                  processProductionRulesIn in varchar2,
3514                                  combinationRulePriorityModeIn in varchar2,
3515                                  combinationRuleThresholdIn in integer,
3516                                  authorityRulePriorityModeIn in varchar2,
3517                                  authorityRuleThresholdIn in integer,
3518                                  exceptionRulePriorityModeIn in varchar2,
3519                                  exceptionRuleThresholdIn in integer,
3520                                  listModRulePriorityModeIn in varchar2,
3521                                  listModRuleThresholdIn in integer,
3522                                  substRulePriorityModeIn in varchar2,
3523                                  substRuleThresholdIn in integer,
3524                                  preRulePriorityModeIn in varchar2,
3525                                  preRuleThresholdIn in integer,
3526                                  postRulePriorityModeIn in varchar2,
3527                                  postRuleThresholdIn in integer,
3528                                  productionRulePriorityModeIn in varchar2,
3529                                  productionRuleThresholdIn in integer,
3530                                  headerItemClassIdIn in integer) is
3531       select
3532         ame_conditions.condition_id condition_id,
3533         ame_conditions.condition_type condition_type,
3534         ame_conditions.attribute_id attribute_id,
3535         ame_conditions.parameter_one parameter_one,
3536         ame_conditions.parameter_two parameter_two,
3537         ame_conditions.parameter_three parameter_three,
3538         ame_conditions.include_lower_limit,
3539         ame_conditions.include_upper_limit,
3540         ame_condition_usages.rule_id rule_id,
3541         ame_rules.rule_type rule_type,
3542         nvl(ame_rules.item_class_id,
3543             headerItemClassIdIn) rule_item_class,
3544         ame_rule_usages.priority priority,
3545         ame_rule_usages.approver_category
3546       from
3547         ame_attributes,
3548         ame_conditions,
3549         ame_condition_usages,
3550         ame_rules,
3551         ame_rule_usages
3552       where
3553         ame_attributes.attribute_id = ame_conditions.attribute_id and
3554         ame_conditions.condition_type <> ame_util.listModConditionType and
3555         ame_conditions.condition_id = ame_condition_usages.condition_id and
3556         ame_condition_usages.rule_id = ame_rules.rule_id and
3557         ame_rules.rule_id = ame_rule_usages.rule_id and
3558         ame_rule_usages.item_id = engAmeApplicationId and
3559         (processPrioritiesIn = ame_util.booleanFalse or
3560          (ame_rules.rule_type = ame_util.combinationRuleType and
3561           (combinationRulePriorityModeIn <> ame_util.absoluteRulePriority or
3562            combinationRuleThresholdIn >= ame_rule_usages.priority)) or
3563          (ame_rules.rule_type = ame_util.authorityRuleType and
3564           (authorityRulePriorityModeIn <> ame_util.absoluteRulePriority or
3565            authorityRuleThresholdIn >= ame_rule_usages.priority)) or
3566          (ame_rules.rule_type = ame_util.exceptionRuleType and
3567           (exceptionRulePriorityModeIn <> ame_util.absoluteRulePriority or
3568            exceptionRuleThresholdIn >= ame_rule_usages.priority)) or
3569          (ame_rules.rule_type = ame_util.listModRuleType and
3570           (listModRulePriorityModeIn <> ame_util.absoluteRulePriority or
3571            listModRuleThresholdIn >= ame_rule_usages.priority)) or
3572          (ame_rules.rule_type = ame_util.substitutionRuleType and
3573           (substRulePriorityModeIn <> ame_util.absoluteRulePriority or
3574            substRuleThresholdIn >= ame_rule_usages.priority)) or
3575          (ame_rules.rule_type = ame_util.preListGroupRuleType and
3576           (preRulePriorityModeIn <> ame_util.absoluteRulePriority or
3577            preRuleThresholdIn >= ame_rule_usages.priority)) or
3578          (ame_rules.rule_type = ame_util.postListGroupRuleType and
3579           (postRulePriorityModeIn <> ame_util.absoluteRulePriority or
3580            postRuleThresholdIn >= ame_rule_usages.priority)) or
3581          (ame_rules.rule_type = ame_util.productionRuleType and
3582           (productionRulePriorityModeIn <> ame_util.absoluteRulePriority or
3583            productionRuleThresholdIn >= ame_rule_usages.priority))) and
3584         (processProductionRulesIn = ame_util.booleanTrue or
3585          ame_rules.rule_type <> ame_util.productionRuleType) and
3586         engEffectiveRuleDate between
3587           ame_attributes.start_date and
3588           nvl(ame_attributes.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3589         engEffectiveRuleDate between
3590           ame_conditions.start_date and
3591           nvl(ame_conditions.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3592         engEffectiveRuleDate between
3593           ame_condition_usages.start_date and
3594           nvl(ame_condition_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3595         engEffectiveRuleDate between
3596           ame_rules.start_date and
3597           nvl(ame_rules.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3598         engEffectiveRuleDate between
3599           ame_rule_usages.start_date and
3600           nvl(ame_rule_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate)
3601       order by
3602         rule_item_class,
3603         ame_rules.rule_type,
3604         ame_rules.rule_id,
3605         ame_attributes.item_class_id;
3606     /*
3607       The tempACU tables are buffers between the active-condition-usage fetch and
3608       the engAC variables.  The temp variables are indexed consecutively, while
3609       the engAC variables are indexed by condition ID or rule ID.
3610     */
3611     tempACUAttributeIds ame_util.idList;
3612     tempACUConditionTypes ame_util.stringList;
3613     tempACUIncludeLowerLimits ame_util.charList;
3614     tempACUIncludeUpperLimits ame_util.charList;
3615     tempACUItemClassIds ame_util.idList;
3616     tempACUParameterOnes ame_util.stringList;
3617     tempACUParameterThrees ame_util.stringList;
3618     tempACUParameterTwos ame_util.longStringList;
3619     tempACURuleApprCats ame_util.charList;
3620     tempACURulePriorities ame_util.idList;
3621     tempACURuleTypes ame_util.idList;
3622     /*
3623       tempACConditionIds is a buffer between the string-value fetch and the
3624       engACStringValue variables.
3625     */
3626     tempACConditionIds ame_util.idList;
3627     /* misc. local variables */
3628     processPriorities ame_util.charType;
3629     processProductions ame_util.charType;
3630     tempConditionID integer;
3631     tempCount integer;
3632     tempItemClassID integer;
3633     tempRuleId integer;
3634     begin
3635       /*
3636         Fetch all condition usages for conditions used by the rules that are used by
3637         the current transaction type.
3638       */
3639       if(engProcessPriorities) then
3640         processPriorities := ame_util.booleanTrue;
3641       else
3642         processPriorities := ame_util.booleanFalse;
3643       end if;
3644       if(engProcessProductionRules) then
3645         processProductions := ame_util.booleanTrue;
3646       else
3647         processProductions := ame_util.booleanFalse;
3648       end if;
3649       open activeCondUsageCursor(processPrioritiesIn => processPriorities,
3650                                  processProductionRulesIn => processProductions,
3651                                  combinationRulePriorityModeIn => engPriorityModes(ame_util.combinationRuleType),
3652                                  combinationRuleThresholdIn => engPriorityThresholds(ame_util.combinationRuleType),
3653                                  authorityRulePriorityModeIn => engPriorityModes(ame_util.authorityRuleType),
3654                                  authorityRuleThresholdIn => engPriorityThresholds(ame_util.authorityRuleType),
3655                                  exceptionRulePriorityModeIn => engPriorityModes(ame_util.exceptionRuleType),
3656                                  exceptionRuleThresholdIn => engPriorityThresholds(ame_util.exceptionRuleType),
3657                                  listModRulePriorityModeIn => engPriorityModes(ame_util.listModRuleType),
3658                                  listModRuleThresholdIn => engPriorityThresholds(ame_util.listModRuleType),
3659                                  substRulePriorityModeIn => engPriorityModes(ame_util.substitutionRuleType),
3660                                  substRuleThresholdIn => engPriorityThresholds(ame_util.substitutionRuleType),
3661                                  preRulePriorityModeIn => engPriorityModes(ame_util.preListGroupRuleType),
3662                                  preRuleThresholdIn => engPriorityThresholds(ame_util.preListGroupRuleType),
3663                                  postRulePriorityModeIn => engPriorityModes(ame_util.postListGroupRuleType),
3664                                  postRuleThresholdIn => engPriorityThresholds(ame_util.postListGroupRuleType),
3665                                  productionRulePriorityModeIn => engPriorityModes(ame_util.productionRuleType),
3666                                  productionRuleThresholdIn => engPriorityThresholds(ame_util.productionRuleType),
3667                                  headerItemClassIdIn => getItemClassId(itemClassNameIn => ame_util.headerItemClassName));
3668       fetch activeCondUsageCursor bulk collect
3669         into
3670           engACUsageConditionIds,
3671           tempACUConditionTypes,
3672           tempACUAttributeIds,
3673           tempACUParameterOnes,
3674           tempACUParameterTwos,
3675           tempACUParameterThrees,
3676           tempACUIncludeLowerLimits,
3677           tempACUIncludeUpperLimits,
3678           engACUsageRuleIds,
3679           tempACURuleTypes,
3680           tempACUItemClassIds,
3681           tempACURulePriorities,
3682           tempACURuleApprCats;
3683       close activeCondUsageCursor;
3684       /*
3685         Loop through the active condition usages, writing their conditions to the
3686         engAC variables each time a new condition is encountered.
3687       */
3688       tempCount := engACUsageConditionIds.count;
3689       for activeCUIndex in 1 .. tempCount loop
3690         tempItemClassID := tempACUItemClassIds(activeCUIndex);
3691         tempConditionID := engACUsageConditionIds(activeCUIndex);
3692         if(not engACAttributeIds.exists(tempConditionID)) then
3693           engACAttributeIds(tempConditionID) := tempACUAttributeIds(activeCUIndex);
3694           engACConditionTypes(tempConditionID) := tempACUConditionTypes(activeCUIndex);
3695           engACParameterOnes(tempConditionID) := tempACUParameterOnes(activeCUIndex);
3696           engACParameterTwos(tempConditionID) := tempACUParameterTwos(activeCUIndex);
3697           engACParameterThrees(tempConditionID) := tempACUParameterThrees(activeCUIndex);
3698           engACIncludeLowerLimits(tempConditionID) := tempACUIncludeLowerLimits(activeCUIndex);
3699           engACIncludeUpperLimits(tempConditionID) := tempACUIncludeUpperLimits(activeCUIndex);
3700         end if;
3701         /*
3702           If this iteration starts an item class, record this iteration's index
3703           in engACUsageFirstIndexes.
3704         */
3705         if(activeCUIndex = 1 or
3706            tempItemClassID <> tempACUItemClassIds(activeCUIndex - 1)) then
3707           engACUsageFirstIndexes(tempItemClassID) := activeCUIndex;
3708         end if;
3709         /*
3710           If this iteration is the last iteration for its item class,
3711           record the item class' active-condition-usage count.
3712         */
3713         if(activeCUIndex = tempCount or
3714            tempItemClassID <> tempACUItemClassIds(activeCUIndex + 1)) then
3715           engACUsageItemClassCounts(tempItemClassID) :=
3716             activeCUIndex - engACUsageFirstIndexes(tempItemClassID) + 1;
3717         end if;
3718         /*
3719           Write the rule priority and rule type into engACUsageRulePriorities indexed by rule ID.
3720           This lets the engine fetch the rule priorities and types efficiently, without carrying
3721           them through all of its algorithms.
3722         */
3723         tempRuleId := engACUsageRuleIds(activeCUIndex);
3724         engACUsageRulePriorities(tempRuleId) := tempACURulePriorities(activeCUIndex);
3725         engACUsageRuleTypes(tempRuleId) := tempACURuleTypes(activeCUIndex);
3726         engACUsageRuleApprCategories(tempRuleId) := tempACURuleApprCats(activeCUIndex);
3727       end loop;
3728       /* Second, fetch the string values for any active conditions on string attributes. */
3729       open activeCondStringValueCursor;
3730       fetch activeCondStringValueCursor bulk collect
3731         into
3732           tempACConditionIds,
3733           engACStringValues;
3734       close activeCondStringValueCursor;
3735       /* Loop through the string conditions, writing them out to the engACStringValue variables. */
3736       tempCount := tempACConditionIds.count;
3737       for stringValueIndex in 1 .. tempCount loop
3738         tempConditionID := tempACConditionIds(stringValueIndex);
3739         /*
3740           If this iteration starts a condition's string-value list, record this
3741           iteration's index in engACStringValueFirstIndexes.
3742         */
3743         if(stringValueIndex = 1 or
3744            tempConditionID <> tempACConditionIds(stringValueIndex - 1)) then
3745           engACStringValueFirstIndexes(tempConditionID) := stringValueIndex;
3746         end if;
3747         /*
3748           engACStringValueCounts(condition_id) is the number of rows in
3749           engACStringValues for the condition with ID condition_id, starting at
3750           the index engACStringValueFirstIndexes(condition_id).
3751         */
3752         if(stringValueIndex = tempCount or
3753            tempConditionID <> tempACConditionIds(stringValueIndex + 1)) then
3754           engACStringValueCounts(tempConditionID) :=
3755             stringValueIndex - engACStringValueFirstIndexes(tempConditionID) + 1;
3756         end if;
3757       end loop;
3758       exception
3759         when others then
3760           if(activeCondUsageCursor%isopen) then
3761             close activeCondUsageCursor;
3762           end if;
3763           if(activeCondStringValueCursor%isopen) then
3764             close activeCondStringValueCursor;
3765           end if;
3766           ame_util.runtimeException(packageNameIn => 'ame_engine',
3767                                     routineNameIn => 'fetchActiveConditionUsages',
3768                                     exceptionNumberIn => sqlcode,
3769                                     exceptionStringIn => sqlerrm);
3770           raise;
3771     end fetchActiveConditionUsages;
3772   procedure fetchApplicableActions as
3773     cursor applicableActionsCursor(ruleIdIn in integer) is
3774       select
3775         ame_actions.action_type_id,
3776         ame_actions.parameter,
3777         ame_actions.parameter_two
3778         from
3779           ame_actions,
3780           ame_action_usages
3781         where
3782           ame_actions.action_id = ame_action_usages.action_id and
3783           ame_action_usages.rule_id = ruleIdIn and
3784           engEffectiveRuleDate between
3785             ame_actions.start_date and
3786             nvl(ame_actions.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3787           engEffectiveRuleDate between
3788             ame_action_usages.start_date and
3789             nvl(ame_action_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate);
3790     productionActionTypeId integer;
3791     tempActionTypeIds ame_util.idList;
3792     tempBoolean boolean;
3793     tempNewRuleIndex integer;
3794     tempRuleCount integer;
3795     tempRuleIndex integer;
3796     tempParameters ame_util.stringList;
3797     tempParameterTwos ame_util.stringList;
3798     tempPerAppProdIndex integer;
3799     begin
3800       /* Initialize per-approver-production variables. */
3801       productionActionTypeId := getActionTypeId(actionTypeNameIn => ame_util.productionActionTypeName);
3802       tempPerAppProdIndex := 0; /* pre-increment */
3803       /* Delete priorities, to make sure they don't get used from here on. */
3804       engAppPriorities.delete;
3805       /* Fetch each applicable rule's actions. */
3806       tempRuleCount := engAppRuleIds.count;
3807       tempNewRuleIndex := tempRuleCount; /* pre-increment tempNewRuleIndex */
3808       for i in 1 .. tempRuleCount loop
3809         tempActionTypeIds.delete;
3810         tempParameters.delete;
3811         tempParameterTwos.delete;
3812         open applicableActionsCursor(ruleIdIn => engAppRuleIds(i));
3813         fetch applicableActionsCursor bulk collect
3814           into
3815             tempActionTypeIds,
3816             tempParameters,
3817             tempParameterTwos;
3818         close applicableActionsCursor;
3819         /* Populate the engAppPerAppProd variables. */
3820         if(engAppRuleTypes(i) <> ame_util.productionRuleType) then
3821           tempBoolean := true; /* Here tempBoolean is true until a production action for this rule is found. */
3822           for j in 1 .. tempActionTypeIds.count loop
3823             if(engActionTypeUsages(tempActionTypeIds(j)) = ame_util.productionRuleType) then
3824               tempPerAppProdIndex := tempPerAppProdIndex + 1;
3825               if(tempBoolean) then
3826                 tempBoolean := false;
3827                 engAppPerAppProdFirstIndexes(engAppRuleIds(i)) := tempPerAppProdIndex;
3828               end if;
3829               engAppPerAppProdRuleIds(tempPerAppProdIndex) := engAppRuleIds(i);
3830               engAppPerAppProdVariableNames(tempPerAppProdIndex) := tempParameters(j);
3831               engAppPerAppProdVariableValues(tempPerAppProdIndex) := tempParameterTwos(j);
3832               tempActionTypeIds(j) := null;  /* This prevents further processing later. */
3833             end if;
3834           end loop;
3835         end if;
3836         /*
3837           If the rule is a production rule, put the first action in the same row as the rule.
3838           Otherwise, put the first non-production action in that row.  (There should always be
3839           at least one non-production action in a non-production rule, and at least one production
3840           action in a production rule.)  Put any remaining actions (non-production actions, unless
3841           the rule is a production rule) in new rows.
3842         */
3843         /* Here tempBoolean is true until the first useable production action is found. */
3844         tempBoolean := true;
3845         for j in 1 .. tempActionTypeIds.count loop
3846           /* Ignore actions with null action-type IDs; these were per-approver production actions. */
3847           if(tempActionTypeIds(j) is not null) then
3848             if(tempBoolean) then
3849               tempBoolean := false;
3850               tempRuleIndex := i;
3851             else
3852               tempNewRuleIndex := tempNewRuleIndex + 1;
3853               tempRuleIndex := tempNewRuleIndex;
3854             end if;
3855             engAppItemClassIds(tempRuleIndex) := engAppItemClassIds(i);
3856             engAppItemIds(tempRuleIndex) := engAppItemIds(i);
3857             engAppRuleIds(tempRuleIndex) := engAppRuleIds(i);
3858             engRuleAppliedYN(tempRuleIndex) := engRuleAppliedYN(i);
3859             engAppRuleTypes(tempRuleIndex) := engAppRuleTypes(i);
3860             engAppApproverCategories(tempRuleIndex) := engAppApproverCategories(i);
3861             engAppActionTypeIds(tempRuleIndex) := tempActionTypeIds(j);
3862             engAppParameters(tempRuleIndex) := tempParameters(j);
3863             engAppParameterTwos(tempRuleIndex) := tempParameterTwos(j);
3864             engAppRuleItemClassIds(tempRuleIndex) := engAppRuleItemClassIds(i);
3865             engAppAppItemIds(tempRuleIndex) := engAppAppItemIds(i);
3866           end if;
3867         end loop;
3868       end loop;
3869       /* Convert combination rules to other rule types. */
3870       for i in 1 .. engAppRuleTypes.count loop
3871         if(engAppRuleTypes(i) = ame_util.combinationRuleType) then
3872           engAppRuleTypes(i) := engActionTypeUsages(engAppActionTypeIds(i));
3873           /* The following if statement was added to resolve bug 3522880. */
3874           if(engAppRuleTypes(i) in (ame_util.listModRuleType, ame_util.substitutionRuleType)) then
3875             engAppLMSubItemClassIds(engAppRuleIds(i)) := engAppRuleItemClassIds(i);
3876             engAppLMSubItemIds(engAppRuleIds(i)) := engAppAppItemIds(i);
3877             engAppRuleItemClassIds(i) := null;
3878             engAppAppItemIds(i) := null;
3879           end if;
3880         end if;
3881       end loop;
3882       /*
3883         Sort all of the engApp lists:  first by item-class order number, then by
3884         item-class ID, then by item ID, then by rule type, then by action-type order
3885         number, then by action-type ID.  See engApp declaration comment block for
3886         details.
3887       */
3888       sortApplicableRules(sortByActionTypeIn => true);
3889       /* Restore the item-class IDs and item IDs of list-modification and substitution rules. */
3890       for i in 1 .. engAppRuleIds.count loop
3891         /* The following if statement was changed to resolve bug 3522880. */
3892         -- if(engAppRuleTypes(i) in (ame_util.listModRuleType, ame_util.substitutionRuleType)) then
3893         if(engAppRuleItemClassIds(i) is null) then
3894           engAppRuleItemClassIds(i) := engAppLMSubItemClassIds(engAppRuleIds(i));
3895           engAppAppItemIds(i) := engAppLMSubItemIds(engAppRuleIds(i));
3896           engRuleAppliedYN(i) := ame_util.booleanFalse;
3897         end if;
3898       end loop;
3899       engAppLMSubItemClassIds.delete;
3900       engAppLMSubItemIds.delete;
3901       exception
3902         when others then
3903           if(applicableActionsCursor%isopen) then
3904             close applicableActionsCursor;
3905           end if;
3906           ame_util.runtimeException(packageNameIn => 'ame_engine',
3907                                     routineNameIn => 'fetchApplicableActions',
3908                                     exceptionNumberIn => sqlcode,
3909                                     exceptionStringIn => sqlerrm);
3910           raise;
3911     end fetchApplicableActions;
3912   procedure fetchAttributeValues(fetchInactivesIn in boolean) as
3913     cursor attributeCursor(applicationIdIn in integer,
3914                            fetchInactivesIn in varchar2) is
3915       select
3916         ame_attributes.attribute_id attribute_id,
3917         ame_attributes.name attribute_name,
3918         ame_attributes.attribute_type attribute_type,
3919         ame_attributes.item_class_id item_class_id,
3920         ame_attribute_usages.query_string,
3921         ame_attribute_usages.is_static
3922         from
3923           ame_attributes,
3924           ame_attribute_usages,
3925           ame_item_class_usages
3926         where
3927           ame_attributes.name not in (ame_util.workflowItemKeyAttribute, ame_util.workflowItemTypeAttribute) and
3928           ame_attributes.attribute_id = ame_attribute_usages.attribute_id and
3929           ame_attribute_usages.application_id = applicationIdIn and
3930           ame_item_class_usages.application_id = applicationIdIn and
3931           ame_attributes.item_class_id = ame_item_class_usages.item_class_id and
3932           (fetchInactivesIn = ame_util.booleanTrue or
3933            ame_attribute_usages.use_count > 0 or
3934            ame_attributes.attribute_id in
3935             (select ame_attributes2.attribute_id
3936               from
3937                 ame_attributes ame_attributes2,
3938                 ame_mandatory_attributes
3939               where
3940                 ame_attributes2.attribute_id = ame_mandatory_attributes.attribute_id and
3941                 ame_mandatory_attributes.action_type_id = -1 and
3942                 engEffectiveRuleDate between
3943                   ame_attributes2.start_date and
3944                   nvl(ame_attributes2.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3945                 engEffectiveRuleDate between
3946                   ame_mandatory_attributes.start_date and
3947                   nvl(ame_mandatory_attributes.end_date - ame_util.oneSecond, engEffectiveRuleDate))) and
3948           engEffectiveRuleDate between
3949             ame_attributes.start_date and
3950             nvl(ame_attributes.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3951           engEffectiveRuleDate between
3952             ame_attribute_usages.start_date and
3953             nvl(ame_attribute_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3954           engEffectiveRuleDate between
3955             ame_item_class_usages.start_date and
3956             nvl(ame_item_class_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate)
3957         /*
3958           The order-by conditions are all necessary.  The second is to break
3959           item_class_order_number ties in a determinate order.  The third is
3960           to display attribute names in alphabetical order on the test tab.
3961           Compare the itemClassUsageCursor cursor in the procedure updateTransactionState.
3962         */
3963         order by
3964           ame_item_class_usages.item_class_order_number,
3965           ame_item_class_usages.item_class_id,
3966           ame_attributes.name;
3967     cursor testTransCurrencyCursor(attributeIdIn in integer) is
3968       select
3969         attribute_value_1,
3970         attribute_value_2,
3971         attribute_value_3
3972       from ame_test_trans_att_values
3973       where
3974         application_id = engAmeApplicationId and
3975         transaction_id = engTransactionId and
3976         attribute_id = attributeIdIn
3977       order by item_id;
3978     cursor testTransNonCurrencyCursor(attributeIdIn in integer) is
3979       select attribute_value_1
3980       from ame_test_trans_att_values
3981       where
3982         application_id = engAmeApplicationId and
3983         transaction_id = engTransactionId and
3984         attribute_id = attributeIdIn
3985       order by item_id;
3986     cursor testTransVariantHeaderCursor(attributeIdIn in integer) is
3987       select attribute_value_1
3988       from ame_test_trans_att_values
3989       where
3990         application_id = engAmeApplicationId and
3991         transaction_id = engTransactionId and
3992         attribute_id = attributeIdIn and
3993         item_class_id = getItemClassId(ame_util.headerItemClassName) and
3994         item_id = engTransactionId;
3995     attributeCount integer;
3996     attributeIds ame_util.idList;
3997     attributeItemClassIds ame_util.idList;
3998     attributeNames ame_util.stringList;
3999     attributeTypes ame_util.stringList;
4000     dynamicCursor integer;
4001     dynamicQuery ame_util.longestStringType;
4002     errorCode integer;
4003     errorMessage ame_util.longestStringType;
4004     fetchInactives varchar2(1);
4005     isStatics ame_util.charList;
4006     queryStrings ame_util.longestStringList;
4007     rowCountException exception;
4008     rowsFound integer;
4009     tempAttributeId integer;
4010     tempAttributeName ame_attributes.name%type;
4011     tempAttributeType ame_attributes.attribute_type%type;
4012     tempAttributeValue1 ame_util.attributeValueType;
4013     tempAttributeValue2 ame_util.attributeValueType;
4014     tempAttributeValue3 ame_util.attributeValueType;
4015     tempAttributeValueIndex integer;
4016     tempAttributeValues1 dbms_sql.varchar2_table;
4017     tempAttributeValues2 dbms_sql.varchar2_table;
4018     tempAttributeValues3 dbms_sql.varchar2_table;
4019     tempItemClassIndex integer;
4020     begin
4021       /*
4022         fetchInactives is necessary because we can't use a PL/SQL boolean variable
4023         in a select statement.
4024       */
4025       if(fetchInactivesIn) then
4026         fetchInactives := ame_util.booleanTrue;
4027       else
4028         fetchInactives := ame_util.booleanFalse;
4029       end if;
4030       /* Bulk fetch attributeCursor into a PL/SQL table. */
4031       open attributeCursor(applicationIdIn => engAmeApplicationId,
4032                            fetchInactivesIn => fetchInactives);
4033       fetch attributeCursor bulk collect
4034         into
4035           attributeIds,
4036           attributeNames,
4037           attributeTypes,
4038           attributeItemClassIds,
4039           queryStrings,
4040           isStatics;
4041       close attributeCursor;
4042       /*
4043         Fetch each attribute's value.  The attributes are in order of their item classes'
4044         item_class_order_numbers, so we can simply load them into the attribute package
4045         variables in index order, noting in engAttributeValueIndexes where each attribute's
4046         values start.
4047       */
4048       attributeCount := attributeIds.count;
4049       /* tempAttributeValueIndex indexes into engAttributeValues1-3.  Pre-increment it. */
4050       tempAttributeValueIndex := 0;
4051       for i in 1 .. attributeCount loop
4052         tempItemClassIndex := engItemClassIndexes(attributeItemClassIds(i));
4053         tempAttributeId := attributeIds(i);
4054         tempAttributeType := attributeTypes(i);
4055         /* Set the attribute's package variables, even if the attribute's item class has no items. */
4056         engAttributeIsStatics(tempAttributeId) := isStatics(i);
4057         engAttributeNames(tempAttributeId) := attributeNames(i);
4058         engAttributeTypes(tempAttributeId) := attributeTypes(i);
4059         engAttributeItemClassIds(tempAttributeId) := attributeItemClassIds(i);
4060         /* Check if the attribute is a variant and set the engAttributeQueries and engAttributeVariant accordingly */
4061         dynamicQuery := ame_util.removeReturns(stringIn => queryStrings(i),
4062                                                replaceWithSpaces => true);
4063         if(checkAttributeVariant(attributeIdIn => tempAttributeId) = ame_util.booleanTrue) then
4064           if ((isStatics(i) = ame_util.booleanFalse) and
4065              (instrb(dynamicQuery, ame_util2.itemClassPlaceHolder) > 0 or
4066               instrb(dynamicQuery, ame_util2.itemIdPlaceHolder) > 0)) then
4067             engAttributeVariant(tempAttributeId) := ame_util.booleanTrue;
4068             engAttributeQueries(tempAttributeId) := queryStrings(i);
4069           end if;
4070         end if;
4071         if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4072           fnd_log.string
4073             (fnd_log.level_statement
4074             ,'ame_engine.fetchAttributeValues'
4075             ,'Attribute ::: ' || engAttributeNames(tempAttributeId) || '(' || tempAttributeId || ')'
4076             );
4077         end if;
4078         /*
4079           Set this attribute's values in engAttributeValues1-3, if the attribute's item class
4080           has any items.
4081         */
4082         if(engItemCounts(tempItemClassIndex) = 0) then
4083           engAttributeValueIndexes(attributeIds(i)) := null;
4084         else
4085           /* (tempAttributeValueIndex will be pre-incremented when it's actually used.) */
4086           engAttributeValueIndexes(attributeIds(i)) := tempAttributeValueIndex + 1;
4087           if(engIsTestTransaction) then
4088               tempAttributeValues1.delete;
4089               tempAttributeValues2.delete;
4090               tempAttributeValues3.delete;
4091               if(checkAttributeVariant(tempAttributeId) = ame_util.booleanTrue) then
4092                 open testTransVariantHeaderCursor(attributeIdIn => tempAttributeId);
4093                 fetch testTransVariantHeaderCursor bulk collect
4094                   into tempAttributeValues1;
4095                 close testTransVariantHeaderCursor;
4096               else
4097                 if(tempAttributeType = ame_util.currencyAttributeType) then
4098                   open testTransCurrencyCursor(attributeIdIn => tempAttributeId);
4099                   fetch testTransCurrencyCursor bulk collect
4100                     into
4101                       tempAttributeValues1,
4102                       tempAttributeValues2,
4103                       tempAttributeValues3;
4104                   close testTransCurrencyCursor;
4105                 else
4106                   open testTransNonCurrencyCursor(attributeIdIn => tempAttributeId);
4107                   fetch testTransNonCurrencyCursor bulk collect
4108                     into tempAttributeValues1;
4109                   close testTransNonCurrencyCursor;
4110                 end if;
4111               end if;
4112               for j in 1 .. tempAttributeValues1.count loop
4113                 tempAttributeValueIndex := tempAttributeValueIndex + 1;
4114                 engAttributeValues1(tempAttributeValueIndex) := tempAttributeValues1(j);
4115                 if(tempAttributeType = ame_util.currencyAttributeType) then
4116                   engAttributeValues2(tempAttributeValueIndex) := tempAttributeValues2(j);
4117                   engAttributeValues3(tempAttributeValueIndex) := tempAttributeValues3(j);
4118                 else
4119                   engAttributeValues2(tempAttributeValueIndex) := null;
4120                   engAttributeValues3(tempAttributeValueIndex) := null;
4121                 end if;
4122                 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4123                   fnd_log.string
4124                     (fnd_log.level_statement
4125                     ,'ame_engine.fetchAttributeValues'
4126                     ,'Attribute Value :' || engAttributeValues1(tempAttributeValueIndex) ||
4127                      ':' || engAttributeValues2(tempAttributeValueIndex) || ':' || engAttributeValues3(tempAttributeValueIndex) || ':'
4128                     );
4129                 end if;
4130               end loop;
4131               if tempAttributeValues1.count = 0 then
4132                 for j in 1 .. engItemCounts(tempItemClassIndex) loop
4133                   tempAttributeValueIndex := tempAttributeValueIndex + 1;
4134                   engAttributeValues1(tempAttributeValueIndex) := null;
4135                   engAttributeValues2(tempAttributeValueIndex) := null;
4136                   engAttributeValues3(tempAttributeValueIndex) := null;
4137                   if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4138                     fnd_log.string
4139                       (fnd_log.level_statement
4140                       ,'ame_engine.fetchAttributeValues'
4141                       ,'Attribute Value :' || engAttributeValues1(tempAttributeValueIndex) ||
4142                        ':' || engAttributeValues2(tempAttributeValueIndex) || ':' || engAttributeValues3(tempAttributeValueIndex) || ':'
4143                       );
4144                   end if;
4145                 end loop;
4146               end if;
4147           else
4148             if(isStatics(i) = ame_util.booleanTrue) then
4149               /*
4150                 Write the static usage into the attribute-value package variables once for each item
4151                 of the attribute's item class.
4152               */
4153               if(attributeTypes(i) = ame_util.currencyAttributeType) then
4154                 ame_util.parseStaticCurAttValue(applicationIdIn => engAmeApplicationId,
4155                                                 attributeIdIn => tempAttributeId,
4156                                                 attributeValueIn => queryStrings(i),
4157                                                 localErrorIn => false,
4158                                                 amountOut => tempAttributeValue1,
4159                                                 currencyOut => tempAttributeValue2,
4160                                                 conversionTypeOut => tempAttributeValue3);
4161               else
4162                 tempAttributeValue1 := queryStrings(i);
4163                 tempAttributeValue2 := null;
4164                 tempAttributeValue3 := null;
4165               end if;
4166               for j in 1 .. engItemCounts(tempItemClassIndex) loop
4167                 tempAttributeValueIndex := tempAttributeValueIndex + 1;
4168                 engAttributeValues1(tempAttributeValueIndex) := tempAttributeValue1;
4169                 engAttributeValues2(tempAttributeValueIndex) := tempAttributeValue2;
4170                 engAttributeValues3(tempAttributeValueIndex) := tempAttributeValue3;
4171                 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4172                   fnd_log.string
4173                     (fnd_log.level_statement
4174                     ,'ame_engine.fetchAttributeValues'
4175                     ,'Attribute Value :' || engAttributeValues1(tempAttributeValueIndex) ||
4176                      ':' || engAttributeValues2(tempAttributeValueIndex) || ':' || engAttributeValues3(tempAttributeValueIndex) || ':'
4177                     );
4178                 end if;
4179               end loop;
4180             else
4181               tempAttributeValues1.delete;
4182               tempAttributeValues2.delete;
4183               tempAttributeValues3.delete;
4184               /*
4185                 We need to do old-style dynamic PL/SQL here to make sure all occurrences of
4186                 ame_util.transactionIdPlaceholder in dynamicQuery get bound.
4187               */
4188               dynamicQuery := ame_util.removeReturns(stringIn => queryStrings(i),
4189                                                      replaceWithSpaces => true);
4190               dynamicCursor := dbms_sql.open_cursor;
4191               dbms_sql.parse(dynamicCursor,
4192                              dynamicQuery,
4193                              dbms_sql.native);
4194               if(instrb(dynamicQuery, ame_util.transactionIdPlaceholder) > 0) then
4195                 dbms_sql.bind_variable(dynamicCursor,
4196                                        ame_util.transactionIdPlaceholder,
4197                                        engTransactionId,
4198                                        50); /* ame_temp_transactions.transaction_id%length doesn't work here. */
4199               end if;
4200               if(instrb(dynamicQuery, ame_util2.itemClassPlaceHolder) > 0) then
4201                 dbms_sql.bind_variable(dynamicCursor,
4202                                        ame_util2.itemClassPlaceHolder,
4203                                        ame_util.headerItemClassName,
4204                                        50); /* ame_temp_transactions.transaction_id%length doesn't work here. */
4205               end if;
4206               if(instrb(dynamicQuery, ame_util2.itemIdPlaceHolder) > 0) then
4207                 dbms_sql.bind_variable(dynamicCursor,
4208                                        ame_util2.itemIdPlaceHolder,
4209                                        engTransactionId,
4210                                        50); /* ame_temp_transactions.transaction_id%length doesn't work here. */
4211               end if;
4212               dbms_sql.define_array(dynamicCursor,
4213                                     1,
4214                                     tempAttributeValues1,
4215                                     ame_util.attributeValueTypeLength,
4216                                     1);
4217               if(tempAttributeType = ame_util.currencyAttributeType) then
4218                 dbms_sql.define_array(dynamicCursor,
4219                                       2,
4220                                       tempAttributeValues2,
4221                                       ame_util.attributeValueTypeLength,
4222                                       1);
4223                 dbms_sql.define_array(dynamicCursor,
4224                                       3,
4225                                       tempAttributeValues3,
4226                                       ame_util.attributeValueTypeLength,
4227                                       1);
4228               end if;
4229               rowsFound := dbms_sql.execute(dynamicCursor);
4230               loop
4231                 rowsFound := dbms_sql.fetch_rows(dynamicCursor);
4232                 dbms_sql.column_value(dynamicCursor,
4233                                       1,
4234                                       tempAttributeValues1);
4235                 if(tempAttributeType = ame_util.currencyAttributeType) then
4236                   dbms_sql.column_value(dynamicCursor,
4237                                         2,
4238                                         tempAttributeValues2);
4239                   dbms_sql.column_value(dynamicCursor,
4240                                         3,
4241                                         tempAttributeValues3);
4242                 end if;
4243                 exit when rowsFound < 100;
4244               end loop;
4245               dbms_sql.close_cursor(dynamicCursor);
4246               /* Make sure the attribute usage returned the right number of rows. */
4247               if(tempAttributeValues1.count <> engItemCounts(tempItemClassIndex)) then
4248                 raise rowCountException;
4249               end if;
4250               /* Transfer the attribute values into the appropriate package variables. */
4251               for j in 1 .. tempAttributeValues1.count loop
4252                 tempAttributeValueIndex := tempAttributeValueIndex + 1;
4253                 engAttributeValues1(tempAttributeValueIndex) := tempAttributeValues1(j);
4254                 if(tempAttributeType = ame_util.currencyAttributeType) then
4255                   engAttributeValues2(tempAttributeValueIndex) := tempAttributeValues2(j);
4256                   engAttributeValues3(tempAttributeValueIndex) := tempAttributeValues3(j);
4257                 else
4258                   engAttributeValues2(tempAttributeValueIndex) := null;
4259                   engAttributeValues3(tempAttributeValueIndex) := null;
4260                 end if;
4261                 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4262                   fnd_log.string
4263                     (fnd_log.level_statement
4264                     ,'ame_engine.fetchAttributeValues'
4265                     ,'Attribute Value :' || engAttributeValues1(tempAttributeValueIndex) ||
4266                      ':' || engAttributeValues2(tempAttributeValueIndex) || ':' || engAttributeValues3(tempAttributeValueIndex) || ':'
4267                     );
4268                 end if;
4269               end loop;
4270             end if;
4271           end if;
4272         end if;
4273       end loop;
4274       exception
4275         when rowCountException then
4276           if(attributeCursor%isopen) then
4277             close attributeCursor;
4278           end if;
4279           if(dbms_sql.is_open(dynamicCursor)) then
4280             dbms_sql.close_cursor(dynamicCursor);
4281           end if;
4282           if(testTransCurrencyCursor%isopen) then
4283             close testTransCurrencyCursor;
4284           end if;
4285           if(testTransNonCurrencyCursor%isopen) then
4286             close testTransNonCurrencyCursor;
4287           end if;
4288           tempAttributeName := ame_attribute_pkg.getName(attributeIdIn => tempAttributeId);
4289           if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4290            fnd_log.string
4291             (fnd_log.level_statement
4292             ,'ame_engine.fetchAttributeValues'
4293             ,'Attribute ::: ' || tempAttributeName || '(' || tempAttributeId || ')'||
4294             'attribute returned ::'||tempAttributeValues1.count||'rows but the number of items for the '||
4295             'itemclass ::'||engItemCounts(tempItemClassIndex)
4296             );
4297           end if;
4298           errorCode := -20001;
4299           errorMessage :=
4300             ame_util.getMessage(applicationShortNameIn =>'PER',
4301                                 messageNameIn   => 'AME_400684_ATR_INV_DYN_USG',
4302                                 tokenNameOneIn  => 'ATTRIBUTE_NAME',
4303                                 tokenValueOneIn => tempAttributeName);
4304           ame_util.runtimeException(packageNameIn => 'ame_engine',
4305                                     routineNameIn => 'fetchAttributeValues',
4306                                     exceptionNumberIn => errorCode,
4307                                     exceptionStringIn => errorMessage);
4308           raise_application_error(errorCode,
4309                                   errorMessage);
4310         when others then
4311           if(attributeCursor%isopen) then
4312             close attributeCursor;
4313           end if;
4314           if(dbms_sql.is_open(dynamicCursor)) then
4315             dbms_sql.close_cursor(dynamicCursor);
4316           end if;
4317           if(testTransCurrencyCursor%isopen) then
4318             close testTransCurrencyCursor;
4319           end if;
4320           if(testTransNonCurrencyCursor%isopen) then
4321             close testTransNonCurrencyCursor;
4322           end if;
4323           tempAttributeName := ame_attribute_pkg.getName(attributeIdIn => tempAttributeId);
4324           errorMessage := sqlerrm;
4325           if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4326            fnd_log.string
4327             (fnd_log.level_statement
4328             ,'ame_engine.fetchAttributeValues'
4329             ,'Attribute ::: ' || tempAttributeName || '(' || tempAttributeId || '),error:'||errorMessage
4330             );
4331            end if;
4332           ame_util.runtimeException(packageNameIn => 'ame_engine',
4333                                     routineNameIn => 'fetchAttributeValues',
4334                                     exceptionNumberIn => sqlcode,
4335                                     exceptionStringIn => errorMessage);
4336           raise;
4337     end fetchAttributeValues;
4338   procedure fetchOtherAttributeValues as
4339     cursor attributeCursor(applicationIdIn in integer) is
4340       select
4341         ame_attributes.attribute_id attribute_id,
4342         ame_attributes.name attribute_name,
4343         ame_attributes.attribute_type attribute_type,
4344         ame_attributes.item_class_id item_class_id,
4345         ame_attribute_usages.query_string,
4346         ame_attribute_usages.is_static
4347         from
4348           ame_attributes,
4349           ame_attribute_usages,
4350           ame_item_class_usages
4351         where
4352           ame_attributes.name not in (ame_util.workflowItemKeyAttribute, ame_util.workflowItemTypeAttribute) and
4353           ame_attributes.attribute_id = ame_attribute_usages.attribute_id and
4354           ame_attribute_usages.application_id = applicationIdIn and
4355           ame_item_class_usages.application_id = applicationIdIn and
4356           ame_attributes.item_class_id = ame_item_class_usages.item_class_id and
4357           (ame_attribute_usages.use_count = 0 and
4358            ame_attributes.attribute_id not in
4359             (select ame_attributes2.attribute_id
4360               from
4361                 ame_attributes ame_attributes2,
4362                 ame_mandatory_attributes
4363               where
4364                 ame_attributes2.attribute_id = ame_mandatory_attributes.attribute_id and
4365                 ame_mandatory_attributes.action_type_id = -1 and
4366                 sysdate between
4367                   ame_attributes2.start_date and
4368                   nvl(ame_attributes2.end_date - ame_util.oneSecond, sysdate) and
4369                 sysdate between
4370                   ame_mandatory_attributes.start_date and
4371                   nvl(ame_mandatory_attributes.end_date - ame_util.oneSecond, sysdate))) and
4372           sysdate between
4373             ame_attributes.start_date and
4374             nvl(ame_attributes.end_date - ame_util.oneSecond, sysdate) and
4375           sysdate between
4376             ame_attribute_usages.start_date and
4377             nvl(ame_attribute_usages.end_date - ame_util.oneSecond, sysdate) and
4378           sysdate between
4379             ame_item_class_usages.start_date and
4380             nvl(ame_item_class_usages.end_date - ame_util.oneSecond, sysdate) and
4381             -- Condition to check whether the attribute is used in the rule
4382             exists
4383             (
4384               select 1
4385                from ame_conditions,
4386                     ame_condition_usages,
4387                     ame_rules,
4388                     ame_rule_usages
4389               where ame_conditions.attribute_id = ame_attributes.attribute_id
4390                 and ame_conditions.condition_id = ame_condition_usages.condition_id
4391                 and ame_condition_usages.rule_id = ame_rules.rule_id
4392                 and ame_rules.rule_id = ame_rule_usages.rule_id
4393                 and ame_rule_usages.item_id = applicationIdIn
4394                 and ((engEffectiveRuleDate between ame_rules.start_date
4395                         and nvl(ame_rules.end_date - (1/86400), engEffectiveRuleDate)))
4396                 and ((engEffectiveRuleDate between ame_rule_usages.start_date
4397                         and nvl(ame_rule_usages.end_date - (1/86400), engEffectiveRuleDate)))
4398                 and engEffectiveRuleDate between ame_conditions.start_date
4399                       and nvl(ame_conditions.end_date - (1/86400), engEffectiveRuleDate)
4400                 and ((engEffectiveRuleDate between ame_condition_usages.start_date
4401                       and nvl(ame_condition_usages.end_date - (1/86400), engEffectiveRuleDate)))
4402               union
4403               select 1
4404                 from ame_mandatory_attributes,
4405                      ame_actions,
4406                      ame_action_usages,
4407                      ame_rules,
4408                      ame_rule_usages
4409                where ame_mandatory_attributes.attribute_id = ame_attributes.attribute_id
4410                  and ame_mandatory_attributes.action_type_id =
4411                         ame_actions.action_type_id
4412                  and ame_actions.action_id = ame_action_usages.action_id
4413                  and ame_action_usages.rule_id = ame_rules.rule_id
4414                  and ame_rules.rule_id = ame_rule_usages.rule_id
4415                  and ame_rule_usages.item_id = applicationIdIn
4416                  and ((engEffectiveRuleDate between ame_rules.start_date
4417                  and nvl(ame_rules.end_date - (1/86400), engEffectiveRuleDate)))
4418                  and ((engEffectiveRuleDate between ame_rule_usages.start_date
4419                  and nvl(ame_rule_usages.end_date - (1/86400), engEffectiveRuleDate)))
4420                  and engEffectiveRuleDate between ame_mandatory_attributes.start_date
4421                  and nvl(ame_mandatory_attributes.end_date - (1/86400), engEffectiveRuleDate)
4422                  and engEffectiveRuleDate between ame_actions.start_date
4423                  and nvl(ame_actions.end_date - (1/86400), engEffectiveRuleDate)
4424                  and ((engEffectiveRuleDate between ame_action_usages.start_date
4425                  and nvl(ame_action_usages.end_date - (1/86400), engEffectiveRuleDate)))
4426             )
4427         /*
4428           The order-by conditions are all necessary.  The second is to break
4429           item_class_order_number ties in a determinate order.  The third is
4430           to display attribute names in alphabetical order on the test tab.
4431           Compare the itemClassUsageCursor cursor in the procedure updateTransactionState.
4432         */
4433         order by
4434           ame_item_class_usages.item_class_order_number,
4435           ame_item_class_usages.item_class_id,
4436           ame_attributes.name;
4437     cursor testTransCurrencyCursor(attributeIdIn in integer) is
4438       select
4439         attribute_value_1,
4440         attribute_value_2,
4441         attribute_value_3
4442       from ame_test_trans_att_values
4443       where
4444         application_id = engAmeApplicationId and
4445         transaction_id = engTransactionId and
4446         attribute_id = attributeIdIn
4447       order by item_id;
4448     cursor testTransNonCurrencyCursor(attributeIdIn in integer) is
4449       select attribute_value_1
4450       from ame_test_trans_att_values
4451       where
4452         application_id = engAmeApplicationId and
4453         transaction_id = engTransactionId and
4454         attribute_id = attributeIdIn
4455       order by item_id;
4456     cursor testTransVariantHeaderCursor(attributeIdIn in integer) is
4457       select attribute_value_1
4458       from ame_test_trans_att_values
4459       where
4460         application_id = engAmeApplicationId and
4461         transaction_id = engTransactionId and
4462         attribute_id = attributeIdIn and
4463         item_class_id = getItemClassId(ame_util.headerItemClassName) and
4464         item_id = engTransactionId;
4465     attributeCount integer;
4466     attributeIds ame_util.idList;
4467     attributeItemClassIds ame_util.idList;
4468     attributeNames ame_util.stringList;
4469     attributeTypes ame_util.stringList;
4470     dynamicCursor integer;
4471     dynamicQuery ame_util.longestStringType;
4472     errorCode integer;
4473     errorMessage ame_util.longestStringType;
4474     fetchInactives varchar2(1);
4475     isStatics ame_util.charList;
4476     queryStrings ame_util.longestStringList;
4477     rowCountException exception;
4478     rowsFound integer;
4479     tempAttributeId integer;
4480     tempAttributeName ame_attributes.name%type;
4481     tempAttributeType ame_attributes.attribute_type%type;
4482     tempAttributeValue1 ame_util.attributeValueType;
4483     tempAttributeValue2 ame_util.attributeValueType;
4484     tempAttributeValue3 ame_util.attributeValueType;
4485     tempAttributeValueIndex integer;
4486     tempAttributeValues1 dbms_sql.varchar2_table;
4487     tempAttributeValues2 dbms_sql.varchar2_table;
4488     tempAttributeValues3 dbms_sql.varchar2_table;
4489     tempItemClassIndex integer;
4490     begin
4491       open attributeCursor(applicationIdIn => engAmeApplicationId);
4492 
4493       fetch attributeCursor bulk collect
4494         into
4495           attributeIds,
4496           attributeNames,
4497           attributeTypes,
4498           attributeItemClassIds,
4499           queryStrings,
4500           isStatics;
4501       close attributeCursor;
4502       /*
4503         Fetch each attribute's value.  The attributes are in order of their item classes'
4504         item_class_order_numbers, so we can simply load them into the attribute package
4505         variables in index order, noting in engAttributeValueIndexes where each attribute's
4506         values start.
4507       */
4508       attributeCount := attributeIds.count;
4509       /* tempAttributeValueIndex indexes into engAttributeValues1-3.  Pre-increment it. */
4510       tempAttributeValueIndex := engAttributeValues1.last;--getMaxValueIndex;
4511       for i in 1 .. attributeCount loop
4512         tempItemClassIndex := engItemClassIndexes(attributeItemClassIds(i));
4513         tempAttributeId := attributeIds(i);
4514         tempAttributeType := attributeTypes(i);
4515         /* Set the attribute's package variables, even if the attribute's item class has no items. */
4516         engAttributeIsStatics(tempAttributeId) := isStatics(i);
4517         engAttributeNames(tempAttributeId) := attributeNames(i);
4518         engAttributeTypes(tempAttributeId) := attributeTypes(i);
4519         engAttributeItemClassIds(tempAttributeId) := attributeItemClassIds(i);
4520         /* Check if the attribute is a variant and set the engAttributeQueries and engAttributeVariant accordingly */
4521         dynamicQuery := ame_util.removeReturns(stringIn => queryStrings(i),
4522                                                replaceWithSpaces => true);
4523         if(checkAttributeVariant(attributeIdIn => tempAttributeId) = ame_util.booleanTrue) then
4524           if ((isStatics(i) = ame_util.booleanFalse) and
4525              (instrb(dynamicQuery, ame_util2.itemClassPlaceHolder) > 0 or
4526               instrb(dynamicQuery, ame_util2.itemIdPlaceHolder) > 0)) then
4527             engAttributeVariant(tempAttributeId) := ame_util.booleanTrue;
4528             engAttributeQueries(tempAttributeId) := queryStrings(i);
4529           end if;
4530         end if;
4531         if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4532           fnd_log.string
4533             (fnd_log.level_statement
4534             ,'ame_engine.fetchOtherAttributeValues'
4535             ,'Attribute ::: ' || engAttributeNames(tempAttributeId) || '(' || tempAttributeId || ')'
4536             );
4537         end if;
4538         /*
4539           Set this attribute's values in engAttributeValues1-3, if the attribute's item class
4540           has any items.
4541         */
4542         if(engItemCounts(tempItemClassIndex) = 0) then
4543           engAttributeValueIndexes(attributeIds(i)) := null;
4544         else
4545           /* (tempAttributeValueIndex will be pre-incremented when it's actually used.) */
4546           engAttributeValueIndexes(attributeIds(i)) := tempAttributeValueIndex + 1;
4547           if(engIsTestTransaction) then
4548               tempAttributeValues1.delete;
4549               tempAttributeValues2.delete;
4550               tempAttributeValues3.delete;
4551               if(checkAttributeVariant(tempAttributeId) = ame_util.booleanTrue) then
4552                 open testTransVariantHeaderCursor(attributeIdIn => tempAttributeId);
4553                 fetch testTransVariantHeaderCursor bulk collect
4554                   into tempAttributeValues1;
4555                 close testTransVariantHeaderCursor;
4556               else
4557                 if(tempAttributeType = ame_util.currencyAttributeType) then
4558                   open testTransCurrencyCursor(attributeIdIn => tempAttributeId);
4559                   fetch testTransCurrencyCursor bulk collect
4560                     into
4561                       tempAttributeValues1,
4562                       tempAttributeValues2,
4563                       tempAttributeValues3;
4564                   close testTransCurrencyCursor;
4565                 else
4566                   open testTransNonCurrencyCursor(attributeIdIn => tempAttributeId);
4567                   fetch testTransNonCurrencyCursor bulk collect
4568                     into tempAttributeValues1;
4569                   close testTransNonCurrencyCursor;
4570                 end if;
4571               end if;
4572               for j in 1 .. tempAttributeValues1.count loop
4573                 tempAttributeValueIndex := tempAttributeValueIndex + 1;
4574                 engAttributeValues1(tempAttributeValueIndex) := tempAttributeValues1(j);
4575                 if(tempAttributeType = ame_util.currencyAttributeType) then
4576                   engAttributeValues2(tempAttributeValueIndex) := tempAttributeValues2(j);
4577                   engAttributeValues3(tempAttributeValueIndex) := tempAttributeValues3(j);
4578                 else
4579                   engAttributeValues2(tempAttributeValueIndex) := null;
4580                   engAttributeValues3(tempAttributeValueIndex) := null;
4581                 end if;
4582                 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4583                   fnd_log.string
4584                     (fnd_log.level_statement
4585                     ,'ame_engine.fetchOtherAttributeValues'
4586                     ,'Attribute Value :' || engAttributeValues1(tempAttributeValueIndex) ||
4587                      ':' || engAttributeValues2(tempAttributeValueIndex) || ':' || engAttributeValues3(tempAttributeValueIndex) || ':'
4588                     );
4589                 end if;
4590               end loop;
4591               if tempAttributeValues1.count = 0 then
4592                 for j in 1 .. engItemCounts(tempItemClassIndex) loop
4593                   tempAttributeValueIndex := tempAttributeValueIndex + 1;
4594                   engAttributeValues1(tempAttributeValueIndex) := null;
4595                   engAttributeValues2(tempAttributeValueIndex) := null;
4596                   engAttributeValues3(tempAttributeValueIndex) := null;
4597                   if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4598                     fnd_log.string
4599                       (fnd_log.level_statement
4600                       ,'ame_engine.fetchOtherAttributeValues'
4601                       ,'Attribute Value :' || engAttributeValues1(tempAttributeValueIndex) ||
4602                        ':' || engAttributeValues2(tempAttributeValueIndex) || ':' || engAttributeValues3(tempAttributeValueIndex) || ':'
4603                       );
4604                   end if;
4605                 end loop;
4606               end if;
4607           else
4608             if(isStatics(i) = ame_util.booleanTrue) then
4609               /*
4610                 Write the static usage into the attribute-value package variables once for each item
4611                 of the attribute's item class.
4612               */
4613               if(attributeTypes(i) = ame_util.currencyAttributeType) then
4614                 ame_util.parseStaticCurAttValue(applicationIdIn => engAmeApplicationId,
4615                                                 attributeIdIn => tempAttributeId,
4616                                                 attributeValueIn => queryStrings(i),
4617                                                 localErrorIn => false,
4618                                                 amountOut => tempAttributeValue1,
4619                                                 currencyOut => tempAttributeValue2,
4620                                                 conversionTypeOut => tempAttributeValue3);
4621               else
4622                 tempAttributeValue1 := queryStrings(i);
4623                 tempAttributeValue2 := null;
4624                 tempAttributeValue3 := null;
4625               end if;
4626               for j in 1 .. engItemCounts(tempItemClassIndex) loop
4627                 tempAttributeValueIndex := tempAttributeValueIndex + 1;
4628                 engAttributeValues1(tempAttributeValueIndex) := tempAttributeValue1;
4629                 engAttributeValues2(tempAttributeValueIndex) := tempAttributeValue2;
4630                 engAttributeValues3(tempAttributeValueIndex) := tempAttributeValue3;
4631                 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4632                   fnd_log.string
4633                     (fnd_log.level_statement
4634                     ,'ame_engine.fetchOtherAttributeValues'
4635                     ,'Attribute Value :' || engAttributeValues1(tempAttributeValueIndex) ||
4636                      ':' || engAttributeValues2(tempAttributeValueIndex) || ':' || engAttributeValues3(tempAttributeValueIndex) || ':'
4637                     );
4638                 end if;
4639               end loop;
4640             else
4641               tempAttributeValues1.delete;
4642               tempAttributeValues2.delete;
4643               tempAttributeValues3.delete;
4644               /*
4645                 We need to do old-style dynamic PL/SQL here to make sure all occurrences of
4646                 ame_util.transactionIdPlaceholder in dynamicQuery get bound.
4647               */
4648               dynamicQuery := ame_util.removeReturns(stringIn => queryStrings(i),
4649                                                      replaceWithSpaces => true);
4650               dynamicCursor := dbms_sql.open_cursor;
4651               dbms_sql.parse(dynamicCursor,
4652                              dynamicQuery,
4653                              dbms_sql.native);
4654               if(instrb(dynamicQuery, ame_util.transactionIdPlaceholder) > 0) then
4655                 dbms_sql.bind_variable(dynamicCursor,
4656                                        ame_util.transactionIdPlaceholder,
4657                                        engTransactionId,
4658                                        50); /* ame_temp_transactions.transaction_id%length doesn't work here. */
4659               end if;
4660               if(instrb(dynamicQuery, ame_util2.itemClassPlaceHolder) > 0) then
4661                 dbms_sql.bind_variable(dynamicCursor,
4662                                        ame_util2.itemClassPlaceHolder,
4663                                        ame_util.headerItemClassName,
4664                                        50); /* ame_temp_transactions.transaction_id%length doesn't work here. */
4665               end if;
4666               if(instrb(dynamicQuery, ame_util2.itemIdPlaceHolder) > 0) then
4667                 dbms_sql.bind_variable(dynamicCursor,
4668                                        ame_util2.itemIdPlaceHolder,
4669                                        engTransactionId,
4670                                        50); /* ame_temp_transactions.transaction_id%length doesn't work here. */
4671               end if;
4672               dbms_sql.define_array(dynamicCursor,
4673                                     1,
4674                                     tempAttributeValues1,
4675                                     ame_util.attributeValueTypeLength,
4676                                     1);
4677               if(tempAttributeType = ame_util.currencyAttributeType) then
4678                 dbms_sql.define_array(dynamicCursor,
4679                                       2,
4680                                       tempAttributeValues2,
4681                                       ame_util.attributeValueTypeLength,
4682                                       1);
4683                 dbms_sql.define_array(dynamicCursor,
4684                                       3,
4685                                       tempAttributeValues3,
4686                                       ame_util.attributeValueTypeLength,
4687                                       1);
4688               end if;
4689               rowsFound := dbms_sql.execute(dynamicCursor);
4690               loop
4691                 rowsFound := dbms_sql.fetch_rows(dynamicCursor);
4692                 dbms_sql.column_value(dynamicCursor,
4693                                       1,
4694                                       tempAttributeValues1);
4695                 if(tempAttributeType = ame_util.currencyAttributeType) then
4696                   dbms_sql.column_value(dynamicCursor,
4697                                         2,
4698                                         tempAttributeValues2);
4699                   dbms_sql.column_value(dynamicCursor,
4700                                         3,
4701                                         tempAttributeValues3);
4702                 end if;
4703                 exit when rowsFound < 100;
4704               end loop;
4705               dbms_sql.close_cursor(dynamicCursor);
4706               /* Make sure the attribute usage returned the right number of rows. */
4707               if(tempAttributeValues1.count <> engItemCounts(tempItemClassIndex)) then
4708                 raise rowCountException;
4709               end if;
4710               /* Transfer the attribute values into the appropriate package variables. */
4711               for j in 1 .. tempAttributeValues1.count loop
4712                 tempAttributeValueIndex := tempAttributeValueIndex + 1;
4713                 engAttributeValues1(tempAttributeValueIndex) := tempAttributeValues1(j);
4714                 if(tempAttributeType = ame_util.currencyAttributeType) then
4715                   engAttributeValues2(tempAttributeValueIndex) := tempAttributeValues2(j);
4716                   engAttributeValues3(tempAttributeValueIndex) := tempAttributeValues3(j);
4717                 else
4718                   engAttributeValues2(tempAttributeValueIndex) := null;
4719                   engAttributeValues3(tempAttributeValueIndex) := null;
4720                 end if;
4721                 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4722                   fnd_log.string
4723                     (fnd_log.level_statement
4724                     ,'ame_engine.fetchOtherAttributeValues'
4725                     ,'Attribute Value :' || engAttributeValues1(tempAttributeValueIndex) ||
4726                      ':' || engAttributeValues2(tempAttributeValueIndex) || ':' || engAttributeValues3(tempAttributeValueIndex) || ':'
4727                     );
4728                 end if;
4729               end loop;
4730             end if;
4731           end if;
4732         end if;
4733       end loop;
4734       exception
4735         when rowCountException then
4736           if(attributeCursor%isopen) then
4737             close attributeCursor;
4738           end if;
4739           if(dbms_sql.is_open(dynamicCursor)) then
4740             dbms_sql.close_cursor(dynamicCursor);
4741           end if;
4742           if(testTransCurrencyCursor%isopen) then
4743             close testTransCurrencyCursor;
4744           end if;
4745           if(testTransNonCurrencyCursor%isopen) then
4746             close testTransNonCurrencyCursor;
4747           end if;
4748           tempAttributeName := ame_attribute_pkg.getName(attributeIdIn => tempAttributeId);
4749           errorCode := -20001;
4750           errorMessage :=
4751             ame_util.getMessage(applicationShortNameIn =>'PER',
4752                                 messageNameIn   => 'AME_400684_ATR_INV_DYN_USG',
4753                                 tokenNameOneIn  => 'ATTRIBUTE_NAME',
4754                                 tokenValueOneIn => tempAttributeName);
4755           ame_util.runtimeException(packageNameIn => 'ame_engine',
4756                                     routineNameIn => 'fetchOtherAttributeValues',
4757                                     exceptionNumberIn => errorCode,
4758                                     exceptionStringIn => errorMessage);
4759           raise_application_error(errorCode,
4760                                   errorMessage);
4761         when others then
4762           if(attributeCursor%isopen) then
4763             close attributeCursor;
4764           end if;
4765           if(dbms_sql.is_open(dynamicCursor)) then
4766             dbms_sql.close_cursor(dynamicCursor);
4767           end if;
4768           if(testTransCurrencyCursor%isopen) then
4769             close testTransCurrencyCursor;
4770           end if;
4771           if(testTransNonCurrencyCursor%isopen) then
4772             close testTransNonCurrencyCursor;
4773           end if;
4774           ame_util.runtimeException(packageNameIn => 'ame_engine',
4775                                     routineNameIn => 'fetchOtherAttributeValues',
4776                                     exceptionNumberIn => sqlcode,
4777                                     exceptionStringIn => sqlerrm);
4778           raise;
4779     end fetchOtherAttributeValues;
4780   procedure fetchConfigVars as
4781     cursor actionTypeConfigCursor is
4782       select
4783         ame_action_type_config.action_type_id,
4784         ame_action_type_config.voting_regime,
4785         ame_action_type_config.order_number,
4786         ame_action_type_config.chain_ordering_mode,
4787         ame_action_types.name,
4788         ame_action_types.procedure_name,
4789         ame_action_type_usages.rule_type
4790         from
4791           ame_action_type_config,
4792           ame_action_types,
4793           ame_action_type_usages
4794         where
4795           ame_action_type_config.application_id = engAmeApplicationId and
4796           ame_action_types.action_type_id = ame_action_type_config.action_type_id and
4797           ame_action_type_usages.action_type_id = ame_action_types.action_type_id and
4798           /*
4799             Only action types for list-creation and exception rules have two action-type usages;
4800             all other action types have exactly one (current) action-type usage each.
4801           */
4802           ame_action_type_usages.rule_type <> ame_util.exceptionRuleType and
4803           engEffectiveRuleDate between
4804             ame_action_type_config.start_date and
4805             nvl(ame_action_type_config.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
4806           engEffectiveRuleDate between
4807             ame_action_types.start_date and
4808             nvl(ame_action_types.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
4809           engEffectiveRuleDate between
4810             ame_action_type_usages.start_date and
4811             nvl(ame_action_type_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate)
4812         order by ame_action_types.action_type_id;
4813     cursor configVarCursor is
4814       select
4815         decode(nvl(application_id,0),0,0,-1) application_id,
4816         /* modified from
4817            application_id to
4818            decode(nvl(application_id,0),0,0,-1) application_id
4819            for the bug 5614208 */
4820         variable_name,
4821         variable_value
4822         from ame_config_vars
4823         where
4824           (application_id = 0 or application_id is null or application_id = engAmeApplicationId) and
4825           /* Config vars can impact the approver list, so use engEffectiveRuleDate here. */
4826           engEffectiveRuleDate between
4827             start_date and
4828             nvl(end_date - ame_util.oneSecond, engEffectiveRuleDate)
4829         order by
4830           variable_name,
4831           application_id;
4832     appIds ame_util.idList;
4833     configVarIndex integer;
4834     variableNames ame_util.stringList;
4835     variableValues ame_util.longStringList;
4836     tempActionTypeId integer;
4837     tempActionTypeIds ame_util.idList;
4838     tempActionTypeNames ame_util.stringList;
4839     tempActionTypePackageNames ame_util.stringList;
4840     tempActionTypeUsages ame_util.idList;
4841     tempChainOrderingModes ame_util.charList;
4842     tempOrderNumbers ame_util.idList;
4843     tempVotingRegimes ame_util.charList;
4844     begin
4845       /* Fetch action-type configuration data. */
4846       open actionTypeConfigCursor;
4847       fetch actionTypeConfigCursor bulk collect
4848         into
4849           tempActionTypeIds,
4850           tempVotingRegimes,
4851           tempOrderNumbers,
4852           tempChainOrderingModes,
4853           tempActionTypeNames,
4854           tempActionTypePackageNames,
4855           tempActionTypeUsages;
4856       close actionTypeConfigCursor;
4857       for actionTypeIndex in 1 .. tempActionTypeIds.count loop
4858         tempActionTypeId := tempActionTypeIds(actionTypeIndex);
4859         engActionTypeChainOrderModes(tempActionTypeId) := tempChainOrderingModes(actionTypeIndex);
4860         engActionTypeOrderNumbers(tempActionTypeId) := tempOrderNumbers(actionTypeIndex);
4861         engActionTypeVotingRegimes(tempActionTypeId) := tempVotingRegimes(actionTypeIndex);
4862         engActionTypeNames(tempActionTypeId) := tempActionTypeNames(actionTypeIndex);
4863         engActionTypePackageNames(tempActionTypeId) := tempActionTypePackageNames(actionTypeIndex);
4864         engActionTypeUsages(tempActionTypeId) := tempActionTypeUsages(actionTypeIndex);
4865       end loop;
4866       /* Fetch configuration-variable values. */
4867       open configVarCursor;
4868       fetch configVarCursor bulk collect
4869         into
4870           appIds,
4871           variableNames,
4872           variableValues;
4873       close configVarCursor;
4874       /*
4875         This loop relies on the ordering of configVarCursor, which groups first by
4876         variable name, then by application ID.  Rows with null application ID follow
4877         rows with non-null application ID in this ordering, so if a transaction type
4878         has defined a value for a configuration variable, the loop will reach this
4879         value before reaching the default value.
4880       */
4881       /*
4882         Always write the first row to the package variables.  (This eliminates a
4883         comparison that would otherwise be necessary within the loop.)
4884       */
4885       engConfigVarNames(1) := variableNames(1);
4886       engConfigVarValues(1) := variableValues(1);
4887       configVarIndex := 1; /* pre-increment */
4888       for i in 2 .. variableValues.count loop
4889         if(variableNames(i) <> variableNames(i - 1)) then
4890           configVarIndex := configVarIndex + 1;
4891           engConfigVarNames(configVarIndex) := variableNames(i);
4892           engConfigVarValues(configVarIndex) := variableValues(i);
4893           if(engConfigVarNames(configVarIndex) = ame_util.forwardingConfigVar) then
4894             parseForwardingBehaviors(forwardingBehaviorsIn => engConfigVarValues(configVarIndex));
4895           elsif(engConfigVarNames(configVarIndex) = ame_util.rulePriorityModesConfigVar) then
4896             parsePriorityModes(priorityModesIn => engConfigVarValues(configVarIndex));
4897           end if;
4898         end if;
4899       end loop;
4900       exception
4901         when others then
4902           if(actionTypeConfigCursor%isopen) then
4903             close actionTypeConfigCursor;
4904           end if;
4905           if(configVarCursor%isopen) then
4906             close configVarCursor;
4907           end if;
4908           ame_util.runtimeException(packageNameIn => 'ame_engine',
4909                                     routineNameIn => 'fetchConfigVars',
4910                                     exceptionNumberIn => sqlcode,
4911                                     exceptionStringIn => sqlerrm);
4912           raise;
4913     end fetchConfigVars;
4914   procedure fetchDeletedApprovers as
4915     cursor deletedApproversCursor(applicationIdIn in integer,
4916                                   transactionIdIn in varchar2) is
4917       select
4918         name,
4919         item_class,
4920         item_id,
4921         approver_category,
4922         action_type_id,
4923         group_or_chain_id,
4924         occurrence,
4925         effective_date,
4926         reason
4927         from ame_temp_deletions
4928         where
4929           application_id = applicationIdIn and
4930           transaction_id = transactionIdIn;
4931     actionTypeIds ame_util.idList;
4932     approverCategories ame_util.charList;
4933     approverNames ame_util.longStringList;
4934     groupOrChainIds ame_util.idList;
4935     itemClasses ame_util.stringList;
4936     itemIds ame_util.stringList;
4937     occurrences ame_util.idList;
4938     upperLimit integer;
4939     tempSuppressionDateList ame_util.dateList;
4940     tempReasonList ame_util.stringList;
4941     begin
4942       open deletedApproversCursor(applicationIdIn => engAmeApplicationId,
4943                                    transactionIdIn => engTransactionId);
4944       fetch deletedApproversCursor bulk collect
4945         into
4946           approverNames,
4947           itemClasses,
4948           itemIds,
4949           approverCategories,
4950           actionTypeIds,
4951           groupOrChainIds,
4952           occurrences,
4953           engSuppressionDateList,
4954           engSupperssionReasonList;
4955       close deletedApproversCursor;
4956       upperLimit := actionTypeIds.count;
4957       for i in 1 .. upperLimit loop
4958         engDeletedApproverList(i).name := approverNames(i);
4959         engDeletedApproverList(i).item_class := itemClasses(i);
4960         engDeletedApproverList(i).item_id := itemIds(i);
4961         engDeletedApproverList(i).approver_category := approverCategories(i);
4962         engDeletedApproverList(i).action_type_id := actionTypeIds(i);
4963         engDeletedApproverList(i).group_or_chain_id := groupOrChainIds(i);
4964         engDeletedApproverList(i).occurrence := occurrences(i);
4965       end loop;
4966       exception
4967         when others then
4968           if(deletedApproversCursor%isopen) then
4969             close deletedApproversCursor;
4970           end if;
4971           ame_util.runtimeException(packageNameIn => 'ame_engine',
4972                                     routineNameIn => 'fetchDeletedApprovers',
4973                                     exceptionNumberIn => sqlcode,
4974                                     exceptionStringIn => sqlerrm);
4975           raise;
4976     end fetchDeletedApprovers;
4977   procedure fetchInsertedApprovers as
4978     cursor insertedApproversCursor(applicationIdIn in integer,
4979                                    transactionIdIn in varchar2) is
4980       select
4981         name,
4982         item_class,
4983         item_id,
4984         nvl(approver_category,ame_util.approvalApproverCategory) approver_category,
4985         api_insertion,
4986         authority,
4987         order_type,
4988         parameter,
4989         special_forwardee,
4990         insertion_order,
4991         effective_date,
4992         reason,
4993         approval_status
4994         from ame_temp_insertions
4995         where
4996           application_id = applicationIdIn and
4997           transaction_id = transactionIdIn
4998           order by insertion_order;
4999     approverApiInsertions ame_util.charList;
5000     approverAuthorities ame_util.charList;
5001     approverCategories ame_util.charList;
5002     approverItemClasses ame_util.stringList;
5003     approverItemIds ame_util.stringList;
5004     approverNames ame_util.longStringList;
5005     approvalStatuses ame_util.stringList;
5006     upperLimit integer;
5007     begin
5008       open insertedApproversCursor(applicationIdIn => engAmeApplicationId,
5009                                    transactionIdIn => engTransactionId);
5010       fetch insertedApproversCursor bulk collect
5011         into
5012           approverNames,
5013           approverItemClasses,
5014           approverItemIds,
5015           approverCategories,
5016           approverApiInsertions,
5017           approverAuthorities,
5018           engInsertionOrderTypeList,
5019           engInsertionParameterList,
5020           engInsertionIsSpecialForwardee,
5021           engInsertionOrderList,
5022           engInsertionDateList,
5023           engInsertionReasonList,
5024           approvalStatuses;
5025       close insertedApproversCursor;
5026       upperLimit := approverAuthorities.count;
5027       for i in 1 .. upperLimit loop
5028         engInsertedApproverList(i).name := approverNames(i);
5029         engInsertedApproverList(i).item_class := approverItemClasses(i);
5030         engInsertedApproverList(i).item_id := approverItemIds(i);
5031         engInsertedApproverList(i).approver_category := approverCategories(i);
5032         engInsertedApproverList(i).api_insertion := approverApiInsertions(i);
5033         engInsertedApproverList(i).authority := approverAuthorities(i);
5034         engInsertedApproverList(i).approval_status := approvalStatuses(i);
5035         ame_approver_type_pkg.getApproverOrigSystemAndId(nameIn =>approverNames(i),
5036                                                          origSystemOut => engInsertedApproverList(i).orig_system,
5037                                                          origSystemIdOut =>engInsertedApproverList(i).orig_system_id);
5038       end loop;
5039       exception
5040         when others then
5041           if(insertedApproversCursor%isopen) then
5042             close insertedApproversCursor;
5043           end if;
5044           ame_util.runtimeException(packageNameIn => 'ame_engine',
5045                                     routineNameIn => 'fetchInsertedApprovers',
5046                                     exceptionNumberIn => sqlcode,
5047                                     exceptionStringIn => sqlerrm);
5048           raise;
5049     end fetchInsertedApprovers;
5050   procedure fetchItemClassData as
5051     cursor itemClassUsageCursor(applicationIdIn in integer) is
5052       select
5053         ame_item_classes.item_class_id,
5054         ame_item_classes.name,
5055         ame_item_class_usages.item_id_query,
5056         ame_item_class_usages.item_class_order_number,
5057         ame_item_class_usages.item_class_par_mode,
5058         ame_item_class_usages.item_class_sublist_mode
5059         from
5060           ame_item_classes,
5061           ame_item_class_usages
5062         where
5063           ame_item_classes.item_class_id = ame_item_class_usages.item_class_id and
5064           ame_item_class_usages.application_id = applicationIdIn and
5065           engEffectiveRuleDate between
5066             ame_item_classes.start_date and
5067             nvl(ame_item_classes.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
5068           engEffectiveRuleDate between
5069             ame_item_class_usages.start_date and
5070             nvl(ame_item_class_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate)
5071         /*
5072           The order-by conditions are both critical.  The second is to break
5073           item_class_order_number ties in a determinate order.  Compare the
5074           attributeCursor cursor in the procedure fetchAttributeValues.
5075         */
5076         order by
5077           ame_item_class_usages.item_class_order_number,
5078           ame_item_class_usages.item_class_id;
5079     cursor testTransItemIdCursor(itemClassIdIn in integer) is
5080       select distinct item_id
5081       from ame_test_trans_att_values
5082       where
5083         application_id = engAmeApplicationId and
5084         transaction_id = engTransactionId and
5085         item_class_id = itemClassIdIn
5086       order by item_id;
5087     dynamicCursor integer;
5088     itemIdQuery ame_util.longestStringType;
5089     itemIds dbms_sql.varchar2_table;
5090     lastEngItemIdIndex integer;
5091     rowsFound integer;
5092     tempIndex integer;
5093     tempItemIdQueries ame_util.longestStringList;
5094     begin
5095       /* Fetch the item-class usages. */
5096       open itemClassUsageCursor(applicationIdIn => engAmeApplicationId);
5097       fetch itemClassUsageCursor bulk collect
5098         into
5099           engItemClassIds,
5100           engItemClassNames,
5101           tempItemIdQueries,
5102           engItemClassOrderNumbers,
5103           engItemClassParModes,
5104           engItemClassSublistModes;
5105       close itemClassUsageCursor;
5106       /* Fetch the item IDs. */
5107       lastEngItemIdIndex := null;
5108       for i in 1 .. engItemClassIds.count loop
5109         engItemClassIndexes(engItemClassIds(i)) := i;
5110         itemIds.delete;
5111         /* Fetch the current item class' item IDs into itemIds. */
5112         if(engItemClassNames(i) = ame_util.headerItemClassName) then
5113           /*
5114             The header item class should always have just one item, with the ID
5115             engTransactionId.  Note that the header item class may not be the
5116             first item class, as the item classes are ordered by item-class order
5117             number.  So lastEngItemIdIndex could be null.
5118           */
5119           if(lastEngItemIdIndex is null) then
5120             engItemClassItemIdIndexes(i) := 1;
5121             lastEngItemIdIndex := 1;
5122           else
5123             engItemClassItemIdIndexes(i) := lastEngItemIdIndex + 1;
5124             lastEngItemIdIndex := lastEngItemIdIndex + 1;
5125           end if;
5126           engItemIds(lastEngItemIdIndex) := engTransactionId;
5127           engItemCounts(i) := 1;
5128         else /* This item class is not the header item class. */
5129           if(engIsTestTransaction) then
5130             open testTransItemIdCursor(itemClassIdIn => engItemClassIds(i));
5131             fetch testTransItemIdCursor bulk collect into itemIds;
5132             close testTransItemIdCursor;
5133             engItemCounts(i) := itemIds.count;
5134             if(itemIds.count > 0) then
5135               if(lastEngItemIdIndex is null) then
5136                 engItemClassItemIdIndexes(i) := 1;
5137                 lastEngItemIdIndex := itemIds.count;
5138               else
5139                 engItemClassItemIdIndexes(i) := lastEngItemIdIndex + 1;
5140                 lastEngItemIdIndex := lastEngItemIdIndex + itemIds.count;
5141               end if;
5142               tempIndex := engItemClassItemIdIndexes(i); /* post-increment tempIndex */
5143               for j in 1 .. itemIds.count loop
5144                 engItemIds(tempIndex) := itemIds(j);
5145                 tempIndex := tempIndex + 1;
5146               end loop;
5147             else
5148               engItemClassItemIdIndexes(i) := null;
5149             end if;
5150           else
5151             itemIdQuery := ame_util.removeReturns(stringIn => tempItemIdQueries(i),
5152                                                   replaceWithSpaces => true);
5153             dynamicCursor := dbms_sql.open_cursor;
5154             dbms_sql.parse(dynamicCursor,
5155                            itemIdQuery,
5156                            dbms_sql.native);
5157             if(instrb(itemIdQuery, ame_util.transactionIdPlaceholder, 1, 1) > 0) then
5158               dbms_sql.bind_variable(dynamicCursor,
5159                                      ame_util.transactionIdPlaceholder,
5160                                      engTransactionId,
5161                                      50); /* ame_temp_transactions.transaction_id%length doesn't work here. */
5162             end if;
5163             dbms_sql.define_array(dynamicCursor,
5164                                   1,
5165                                   itemIds,
5166                                   100,
5167                                   1);
5168             rowsFound := dbms_sql.execute(dynamicCursor);
5169             loop
5170               rowsFound := dbms_sql.fetch_rows(dynamicCursor);
5171               dbms_sql.column_value(dynamicCursor,
5172                                     1,
5173                                     itemIds);
5174               exit when rowsFound < 100;
5175             end loop;
5176             dbms_sql.close_cursor(dynamicCursor);
5177             /* Copy the item IDs into engItemIds. */
5178             engItemCounts(i) := itemIds.count;
5179             if(itemIds.count > 0) then
5180               if(lastEngItemIdIndex is null) then
5181                 engItemClassItemIdIndexes(i) := 1;
5182                 lastEngItemIdIndex := itemIds.count;
5183               else
5184                 engItemClassItemIdIndexes(i) := lastEngItemIdIndex + 1;
5185                 lastEngItemIdIndex := lastEngItemIdIndex + itemIds.count;
5186               end if;
5187               tempIndex := engItemClassItemIdIndexes(i); /* post-increment tempIndex */
5188               for j in 1 .. itemIds.count loop
5189                 engItemIds(tempIndex) := itemIds(j);
5190                 tempIndex := tempIndex + 1;
5191               end loop;
5192             else
5193               engItemClassItemIdIndexes(i) := null;
5194             end if;
5195           end if;
5196         end if;
5197       if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
5198         fnd_log.string
5199           (fnd_log.level_statement
5200                  ,'ame_engine.fetchItemClassData'
5201                  ,'Item Class ::' || engItemClassNames(i) ||
5202                   ':' || 'has ' || ':' || engItemCounts(i) || ':items'
5203            );
5204       end if;
5205       end loop;
5206       exception
5207         when others then
5208           if(itemClassUsageCursor%isopen) then
5209             close itemClassUsageCursor;
5210           end if;
5211           if(testTransItemIdCursor%isopen) then
5212             close testTransItemIdCursor;
5213           end if;
5214           ame_util.runtimeException(packageNameIn => 'ame_engine',
5215                                     routineNameIn => 'fetchItemClassData',
5216                                     exceptionNumberIn => sqlcode,
5217                                     exceptionStringIn => sqlerrm);
5218           raise;
5219     end fetchItemClassData;
5220   procedure fetchFndApplicationId(applicationIdIn in integer,
5221                                   fndApplicationIdOut out nocopy integer,
5222                                   transactionTypeIdOut out nocopy varchar2) as
5223     begin
5224       select
5225         fnd_application_id,
5226         transaction_type_id
5227         into
5228           fndApplicationIdOut,
5229           transactionTypeIdOut
5230         from ame_calling_apps
5231         where
5232           application_id = applicationIdIn and
5233           /* Don't use engEffectiveRuleDate here. */
5234           sysdate between
5235             start_date and
5236             nvl(end_date - ame_util.oneSecond, sysdate) and
5237           rownum < 2; /* Avoids second fetch otherwise required by ANSI standard to check for too many rows. */
5238       exception
5239         when others then
5240           ame_util.runtimeException(packageNameIn => 'ame_engine',
5241                                     routineNameIn => 'fetchFndApplicationId',
5242                                     exceptionNumberIn => sqlcode,
5243                                     exceptionStringIn => sqlerrm);
5244           fndApplicationIdOut := null;
5245           transactionTypeIdOut := null;
5246           raise;
5247     end fetchFndApplicationId;
5248   procedure fetchOldApprovers as
5249     cursor oldApproversCursor(applicationIdIn in integer,
5250                               transactionIdIn in varchar2) is
5251       select
5252         name,
5253         item_class,
5254         item_id,
5255         approver_category,
5256         api_insertion,
5257         authority,
5258         approval_status,
5259         action_type_id,
5260         group_or_chain_id,
5261         occurrence
5262         from ame_temp_old_approver_lists
5263         where
5264           application_id = applicationIdIn and
5265           transaction_id = transactionIdIn
5266           order by order_number;
5267     actionTypeIds ame_util.idList;
5268     approverApiInsertions ame_util.charList;
5269     approverAuthorities ame_util.charList;
5270     approverCategories ame_util.charList;
5271     approverNames ame_util.longStringList;
5272     approverStatuses ame_util.stringList;
5273     groupOrChainIds ame_util.idList;
5274     itemClasses ame_util.stringList;
5275     itemIds ame_util.stringList;
5276     occurrences ame_util.idList;
5277     upperLimit integer;
5278     begin
5279       open oldApproversCursor(applicationIdIn => engAmeApplicationId,
5280                               transactionIdIn => engTransactionId);
5281       fetch oldApproversCursor bulk collect
5282         into
5283           approverNames,
5284           itemClasses,
5285           itemIds,
5286           approverCategories,
5287           approverApiInsertions,
5288           approverAuthorities,
5289           approverStatuses,
5290           actionTypeIds,
5291           groupOrChainIds,
5292           occurrences;
5293       close oldApproversCursor;
5294       upperLimit := approverAuthorities.count;
5295       for i in 1 .. upperLimit loop
5296         engOldApproverList(i).name := approverNames(i);
5297         engOldApproverList(i).item_class := itemClasses(i);
5298         engOldApproverList(i).item_id := itemIds(i);
5299         engOldApproverList(i).approver_category := approverCategories(i);
5300         engOldApproverList(i).api_insertion := approverApiInsertions(i);
5301         engOldApproverList(i).authority := approverAuthorities(i);
5302         engOldApproverList(i).action_type_id := actionTypeIds(i);
5303         engOldApproverList(i).group_or_chain_id := groupOrChainIds(i);
5304         engOldApproverList(i).occurrence := occurrences(i);
5305         engOldApproverList(i).source := null;
5306         /* Force recalculation of suppressed and repeated statuses with each engine cycle. */
5307         if approverStatuses(i) in (ame_util.suppressedStatus, ame_util.repeatedStatus) then
5308           engOldApproverList(i).approval_status := null;
5309         else
5310           engOldApproverList(i).approval_status := approverStatuses(i);
5311         end if;
5312       end loop;
5313       exception
5314         when others then
5315           if(oldApproversCursor%isopen) then
5316             close oldApproversCursor;
5317           end if;
5318           ame_util.runtimeException(packageNameIn => 'ame_engine',
5319                                     routineNameIn => 'fetchOldApprovers',
5320                                     exceptionNumberIn => sqlcode,
5321                                     exceptionStringIn => sqlerrm);
5322           raise;
5323     end fetchOldApprovers;
5324   procedure fetchRuntimeGroup(groupIdIn in integer) as
5325     cursor groupMemberCursor(groupIdIn in integer) is
5326       select
5327         orig_system,
5328         orig_system_id,
5329         parameter,
5330         upper(parameter_name),
5331         query_string,
5332         order_number,
5333         decode(parameter_name,
5334                ame_util.approverOamGroupId, null,
5335                ame_approver_type_pkg.getWfRolesName(orig_system, orig_system_id)) name,
5336         decode(parameter_name,
5337                ame_util.approverOamGroupId, null,
5338                ame_approver_type_pkg.getApproverDisplayName2(orig_system, orig_system_id)) display_name
5339         from ame_approval_group_members
5340         where
5341           approval_group_id = groupIdIn
5342         order by order_number;
5343     badDynamicMemberException exception;
5344     dynamicCursor integer;
5345     colonLocation1 integer;
5346     colonLocation2 integer;
5347     displayNames ame_util.longStringList;
5348     errorCode integer;
5349     errorMessage ame_util.longestStringType;
5350     names ame_util.longStringList;
5351     orderNumbers ame_util.idList;
5352     origSystemIds ame_util.idList;
5353     origSystems ame_util.stringList;
5354     outputIndex integer;
5355     parameters ame_util.longStringList;
5356     queryStrings ame_util.longestStringList;
5357     rowsFound integer;
5358     tempGroupMembers dbms_sql.Varchar2_Table;
5359     upperParameterNames ame_util.stringList;
5360     tempApproverType ame_util.stringType;
5361     tempApproverId   ame_util.stringType;
5362     tempname         wf_roles.name%type;
5363     begin
5364       if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
5365         fnd_log.string
5366           (fnd_log.level_statement
5367             ,'ame_engine.fetchRuntimeGroup'
5368             ,'evaluating the group::'||ame_approval_group_pkg.getName(approvalGroupIdIn => groupIdIn
5369                                                                       ,effectiveDateIn   => engEffectiveRuleDate)
5370            );
5371       end if;
5372       open groupMemberCursor(groupIdIn => groupIdIn);
5373       fetch groupMemberCursor bulk collect
5374         into
5375           origSystems,
5376           origSystemIds,
5377           parameters,
5378           upperParameterNames,
5379           queryStrings,
5380           orderNumbers,
5381           names,
5382           displayNames;
5383       close groupMemberCursor;
5384       if (engGroupUseItemBind.exists(groupIdIn)) then
5385         /* This is not the first time this query is being executed, so find and delete all old approvers in this group. */
5386         for n in 1 .. engGroupMemberGroupIds.count loop
5387           if( engGroupMemberGroupIds(n) = groupIdIn ) then
5388             -- delete all occurrences of this
5389              engGroupMemberGroupIds(n) := null;
5390              engGroupMemberNames(n) := null;
5391              engGroupMemberOrderNumbers(n) := null;
5392              engGroupMemberDisplayNames(n) := null;
5393              engGroupMemberOrigSystems(n) := null;
5394              engGroupMemberOrigSystemIds(n) := null;
5395           end if;
5396         end loop;
5397         -- compact list
5398         outputIndex := engGroupMemberGroupIds.first;
5399         for i in 1 .. engGroupMemberGroupIds.count loop
5400           if(i <> outputIndex) then /* (Don't copy a row onto itself.) */
5401             engGroupMemberGroupIds(i) := engGroupMemberGroupIds(outputIndex);
5402             engGroupMemberNames(i) := engGroupMemberNames(outputIndex);
5403             engGroupMemberOrderNumbers(i) := engGroupMemberOrderNumbers(outputIndex);
5404             engGroupMemberDisplayNames(i) := engGroupMemberDisplayNames(outputIndex);
5405             engGroupMemberOrigSystems(i) := engGroupMemberOrigSystems(outputIndex);
5406             engGroupMemberOrigSystemIds(i) := engGroupMemberOrigSystemIds(outputIndex);
5407           end if;
5408           outputIndex := engGroupMemberGroupIds.next(outputIndex);
5409         end loop;
5410         engGroupMemberGroupIds.delete(outputIndex, engGroupMemberGroupIds.count);
5411       end if;
5412       outputIndex := engGroupMemberGroupIds.count; /* pre-increment */
5413       for i in 1 .. parameters.count loop
5414         tempGroupMembers.delete; -- for bug 4616570
5415         if(upperParameterNames(i) = upper(ame_util.approverOamGroupId)) then
5416           dynamicCursor := dbms_sql.open_cursor;
5417           dbms_sql.parse(dynamicCursor,
5418                          ame_util.removeReturns(stringIn => queryStrings(i),
5419                                                 replaceWithSpaces => true),
5420                          dbms_sql.native);
5421           engGroupUseItemBind(groupIdIn) := ame_util.booleanFalse;
5422           if(instrb(queryStrings(i),
5423                     ame_util.transactionIdPlaceholder) > 0) then
5424             dbms_sql.bind_variable(dynamicCursor,
5425                                    ame_util.transactionIdPlaceholder,
5426                                    engTransactionId,
5427                                    50);
5428           end if;
5429           if(instrb(queryStrings(i),
5430                     ame_util2.itemClassPlaceHolder) > 0) then
5431             dbms_sql.bind_variable(dynamicCursor,
5432                                    ame_util2.itemClassPlaceHolder,
5433                                    getItemClassName(itemClassIdIn => engAppRuleItemClassIds(engAppHandlerFirstIndex)),
5434                                    50);
5435             engGroupUseItemBind(groupIdIn) := ame_util.booleanTrue;
5436           end if;
5437           if(instrb(queryStrings(i),
5438                     ame_util2.itemIdPlaceHolder) > 0) then
5439             dbms_sql.bind_variable(dynamicCursor,
5440                                    ame_util2.itemIdPlaceHolder,
5441                                    engAppAppItemIds(engAppHandlerFirstIndex),
5442                                    50);
5443             engGroupUseItemBind(groupIdIn) := ame_util.booleanTrue;
5444           end if;
5445           dbms_sql.define_array(dynamicCursor,
5446                                 1,
5447                                 tempGroupMembers,
5448                                 100,
5449                                 1);
5450           rowsFound := dbms_sql.execute(dynamicCursor);
5451           loop
5452             rowsFound := dbms_sql.fetch_rows(dynamicCursor);
5453             dbms_sql.column_value(dynamicCursor,
5454                                   1,
5455                                   tempGroupMembers);
5456             exit when rowsFound < 100;
5457           end loop;
5458           dbms_sql.close_cursor(dynamicCursor);
5459           /*
5460             Dynamic groups' query strings may return rows having one of two forms:
5461               (1) approver_type:approver_id
5462               (2) orig_system:orig_system_id
5463           */
5464           for j in 1 .. tempGroupMembers.count loop
5465             tempApproverType := null;
5466             tempApproverId   := null;
5467             colonLocation1 := instrb(tempGroupMembers(j), ':', 1, 1);
5468             if(colonLocation1 = 0) then
5469               raise badDynamicMemberException;
5470             end if;
5471             outputIndex := outputIndex + 1;
5472             tempApproverId := substrb(tempGroupMembers(j),instrb(tempGroupMembers(j), ':', 1, 1) + 1);
5473             tempApproverType := substrb(tempGroupMembers(j), 1, (instrb(tempGroupMembers(j), ':', 1, 1) - 1));
5474             if tempApproverId is not null and lengthb(trim(tempApproverId)) > 0
5475                and tempApproverType is not null and lengthb(trim(tempApproverType)) > 0 then
5476               engGroupMemberGroupIds(outputIndex) := groupIdIn;
5477               engGroupMemberOrderNumbers(outputIndex) := j;
5478               if upper(tempApproverType) = upper(ame_util.approverPersonId) then /* old style */
5479                 engGroupMemberOrigSystems(outputIndex)   := ame_util.perOrigSystem;
5480                 engGroupMemberOrigSystemIds(outputIndex) := tempApproverId;
5481               elsif upper(tempApproverType) = upper(ame_util.approverUserId) then /* old style */
5482                 engGroupMemberOrigSystems(outputIndex)   := ame_util.fndUserOrigSystem;
5483                 engGroupMemberOrigSystemIds(outputIndex) := tempApproverId;
5484               else /* 11i10 style */
5485                 begin
5486                   tempName := ame_approver_type_pkg.getWfRolesName(tempApproverType,tempApproverId);
5487                 exception
5488                   when others then
5489                     raise badDynamicMemberException;
5490                 end;
5491                 engGroupMemberOrigSystems(outputIndex)   := tempApproverType;
5492                 engGroupMemberOrigSystemIds(outputIndex) := tempApproverId;
5493               end if;
5494               ame_approver_type_pkg.getWfRolesNameAndDisplayName(
5495                 origSystemIn => engGroupMemberOrigSystems(outputIndex),
5496                 origSystemIdIn => engGroupMemberOrigSystemIds(outputIndex),
5497                 nameOut => engGroupMemberNames(outputIndex),
5498                 displayNameOut => engGroupMemberDisplayNames(outputIndex));
5499             end if;
5500           end loop;
5501         else /* Copy the static group into the engGroup caches. */
5502           outputIndex := outputIndex + 1;
5503           engGroupUseItemBind(groupIdIn) := ame_util.booleanFalse;
5504           engGroupMemberGroupIds(outputIndex) := groupIdIn;
5505           engGroupMemberNames(outputIndex) := names(i);
5506           engGroupMemberOrderNumbers(outputIndex) := orderNumbers(i);
5507           engGroupMemberDisplayNames(outputIndex) := displayNames(i);
5508           engGroupMemberOrigSystems(outputIndex) := origSystems(i);
5509           engGroupMemberOrigSystemIds(outputIndex) := origSystemIds(i);
5510         end if;
5511       end loop;
5512       if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
5513         fnd_log.string
5514           (fnd_log.level_statement
5515             ,'ame_engine.fetchRuntimeGroup'
5516             ,'Completed the group evaluation::'||ame_approval_group_pkg.getName(approvalGroupIdIn => groupIdIn
5517                                                                       ,effectiveDateIn   => engEffectiveRuleDate)
5518            );
5519       end if;
5520       exception
5521         when badDynamicMemberException then
5522           errorCode := -20001;
5523           errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
5524                                               messageNameIn => 'AME_400771_ENG_INVALID_DYN_GRP',
5525                                               tokenNameOneIn  => 'GROUP_NAME',
5526                                               tokenValueOneIn => ame_approval_group_pkg.getName(approvalGroupIdIn => groupIdIn
5527                                                                                                ,effectiveDateIn   => engEffectiveRuleDate));
5528           ame_util.runtimeException(packageNameIn => 'ame_engine',
5529                                     routineNameIn => 'fetchRuntimeGroup',
5530                                     exceptionNumberIn => errorCode,
5531                                     exceptionStringIn => errorMessage);
5532           raise_application_error(errorCode,
5533                                   errorMessage);
5534         when others then
5535           if(groupMemberCursor%isopen) then
5536             close groupMemberCursor;
5537           end if;
5538           ame_util.runtimeException(packageNameIn => 'ame_engine',
5539                                     routineNameIn => 'fetchRuntimeGroup',
5540                                     exceptionNumberIn => sqlcode,
5541                                     exceptionStringIn => sqlerrm);
5542           raise;
5543     end fetchRuntimeGroup;
5544   /* This procedure is used to assign calculate min_order and max_order */
5545   /* of each node in the approver tree                                  */
5546   /* It also populates the approver_order_number of the engStApprovers  */
5547   procedure finalizeTree
5548     (parentIndexIn        in            integer default 1
5549     ,maximumOrderOut         out nocopy integer
5550     ,approvalStatusOut       out nocopy integer
5551     ,rejectedItemsExistOut   out nocopy boolean) is
5552     currentTreeNodeIndex           integer;
5553     maximumOrderOfChildren         integer;
5554     approvalStatusOfChildren       integer;
5555     previousTreeNodeIndex          integer;
5556     currentApproverApprovalStatus  varchar2(50);
5557     currentApproverCategory        varchar2(1);
5558     currentApproverIndex           integer;
5559     nextSuspendedItemIndex         integer;
5560     hasRejectedChildren            boolean;
5561     currentTreeNodeRejectionStatus boolean;
5562   begin
5563     if engStApproversTree.count > 0 then
5564       approvalStatusOfChildren := ame_util.unknownStatus;
5565       currentTreeNodeIndex := engStApproversTree(parentIndexIn).child_index;
5566       if currentTreeNodeIndex = ame_util.noChildIndex then
5567         /* This is an approver node                                     */
5568         /* 1. For a approver node the maximum order number is same      */
5569         /*    as parents minimum order number                           */
5570         /* 2. The approvalStatus of the node is set based on            */
5571         /*    approvers approval status                                 */
5572         /* 3. If the approvers approval status is ame_util.rejectStatus */
5573         /*    then the approvers item class and item id are populated   */
5574         /*    into the global list of rejected items                    */
5575         maximumOrderOut := engStApproversTree(parentIndexIn).min_order;
5576         currentApproverApprovalStatus :=
5577           engStApprovers(engStApproversTree(parentIndexIn).approver_index).approval_status;
5578         currentApproverCategory :=
5579           engStApprovers(engStApproversTree(parentIndexIn).approver_index).approver_category;
5580         if currentApproverApprovalStatus is null or
5581            currentApproverApprovalStatus in (ame_util.repeatedStatus) then
5582           approvalStatusOut := ame_util.notStartedStatus;
5583         elsif currentApproverApprovalStatus in (ame_util.approvedStatus
5584                                                ,ame_util.rejectStatus
5585                                                ,ame_util.beatByFirstResponderStatus
5586                                                ,ame_util.approvedByRepeatedStatus
5587                                                ,ame_util.rejectedByRepeatedStatus
5588                                                ,ame_util.suppressedStatus
5589                                                ,ame_util.noResponseStatus
5590                                                ,ame_util.forwardStatus
5591                                                ,ame_util.approveAndForwardStatus
5592                                                ,ame_util2.reassignStatus
5593                                                ,ame_util2.noResponseByRepeatedStatus
5594                                                ,ame_util2.forwardByRepeatedStatus) or
5595              (currentApproverCategory = ame_util.fyiApproverCategory and
5596               (currentApproverApprovalStatus in (ame_util.notifiedStatus,
5597                                                  ame_util.notifiedByRepeatedStatus))) then
5598           approvalStatusOut := ame_util.completedStatus;
5599         elsif currentApproverApprovalStatus not in (ame_util.approvedStatus
5600                                                    ,ame_util.rejectStatus
5601                                                    ,ame_util.beatByFirstResponderStatus
5602                                                    ,ame_util.approvedByRepeatedStatus
5603                                                    ,ame_util.rejectedByRepeatedStatus
5604                                                    ,ame_util.suppressedStatus) then
5605           approvalStatusOut := ame_util.startedStatus;
5606         end if;
5607         if currentApproverApprovalStatus = ame_util.rejectStatus
5608            or currentApproverApprovalStatus = ame_util.rejectedByRepeatedStatus then
5609           rejectedItemsExistOut := true;
5610           /* Populate the list of rejected items and item classes */
5611           nextSuspendedItemIndex := engStSuspendedItems.count + 1;
5612           engStSuspendedItems(nextSuspendedItemIndex)
5613             := engStApprovers(engStApproversTree(parentIndexIn).approver_index).item_id;
5614           engStSuspendedItemClasses(nextSuspendedItemIndex)
5615             := engStApprovers(engStApproversTree(parentIndexIn).approver_index).item_class;
5616         else
5617           rejectedItemsExistOut := false;
5618         end if;
5619       else
5620         /* This is a non approver node                               */
5621         /* 1.For a non approver node find the maximum order number   */
5622         /*   among its children and assign it as the maximum order   */
5623         /*   number of the parent node                               */
5624         /* 2.The approvalStatus of the node is determined by finding */
5625         /*   the aggregate status of all its child nodes             */
5626         /* 3.The current node is flagged as rejected if any of its   */
5627         /*   children have a rejectedStatus                          */
5628         previousTreeNodeIndex := ame_util.invalidTreeIndex;
5629         currentTreeNodeRejectionStatus := false;
5630         maximumOrderOfChildren := engStApproversTree(parentIndexIn).min_order;
5631         loop
5632           if previousTreeNodeIndex = ame_util.invalidTreeIndex then
5633             engStApproversTree(currentTreeNodeIndex).min_order
5634                             := engStApproversTree(parentIndexIn).min_order;
5635           elsif engStApproversTree(currentTreeNodeIndex).order_number
5636                    = engStApproversTree(previousTreeNodeIndex).order_number then
5637             engStApproversTree(currentTreeNodeIndex).min_order
5638                             := engStApproversTree(previousTreeNodeIndex).min_order;
5639           else
5640             engStApproversTree(currentTreeNodeIndex).min_order
5641                             := maximumOrderOfChildren + 1;
5642           end if;
5643           ame_engine.finalizeTree
5644             (parentIndexIn          => currentTreeNodeIndex
5645             ,maximumOrderOut        => engStApproversTree(currentTreeNodeIndex).max_order
5646             ,approvalStatusOut      => engStApproversTree(currentTreeNodeIndex).status
5647             ,rejectedItemsExistOut  => hasRejectedChildren);
5648           if hasRejectedChildren then
5649             currentTreeNodeRejectionStatus := true;
5650           end if;
5651           if engStApproversTree(currentTreeNodeIndex).max_order
5652                                                        > maximumOrderOfChildren then
5653             maximumOrderOfChildren := engStApproversTree(currentTreeNodeIndex).max_order;
5654           end if;
5655           if engStApproversTree(currentTreeNodeIndex).approver_index
5656                                                        <> ame_util.noApproverIndex then
5657             currentApproverIndex := engStApproversTree(currentTreeNodeIndex).approver_index;
5658             engStApprovers(currentApproverIndex).approver_order_number
5659                          := engStApproversTree(currentTreeNodeIndex).max_order;
5660           end if;
5661           if (engStApproversTree(currentTreeNodeIndex).status = ame_util.notStartedStatus
5662                and approvalStatusOfChildren = ame_util.completedStatus)
5663             or (engStApproversTree(currentTreeNodeIndex).status = ame_util.completedStatus
5664                and approvalStatusOfChildren = ame_util.notStartedStatus) then
5665             approvalStatusOfChildren := ame_util.startedStatus;
5666           elsif engStApproversTree(currentTreeNodeIndex).status
5667                            > approvalStatusOfChildren then
5668             approvalStatusOfChildren := engStApproversTree(currentTreeNodeIndex).status;
5669           end if;
5670           previousTreeNodeIndex := currentTreeNodeIndex;
5671           currentTreeNodeIndex := engStApproversTree(currentTreeNodeIndex).sibling_index;
5672           exit when currentTreeNodeIndex = ame_util.noSiblingIndex;
5673         end loop;
5674         maximumOrderOut := maximumOrderOfChildren;
5675         /* If the node has supended children and the node is below the item level then */
5676         /* its status is set to completed as no more approvers are to be fetched from  */
5677         /* below this node                                                             */
5678         if currentTreeNodeRejectionStatus and
5679            engStApproversTree(parentIndexIn).tree_level > 1 then
5680           approvalStatusOut := ame_util.completedStatus;
5681         elsif approvalStatusOfChildren = ame_util.unknownStatus then
5682           approvalStatusOut := ame_util.notStartedStatus;
5683         else
5684           approvalStatusOut := approvalStatusOfChildren;
5685         end if;
5686         rejectedItemsExistOut := currentTreeNodeRejectionStatus;
5687       end if;
5688     end if;
5689   exception
5690     when others then
5691       ame_util.runtimeException(packageNameIn => 'ame_engine',
5692                                 routineNameIn => 'finalizeTree',
5693                                 exceptionNumberIn => sqlcode,
5694                                 exceptionStringIn => sqlerrm);
5695       raise;
5696   end finalizeTree;
5697   /* getAllApprovers is for amem0013.sql backwards compatibility only.  Do not use it elsewhere. */
5698   procedure getAllApprovers(approversOut out nocopy ame_util.approversTable) as
5699     begin
5700       ame_api.getAllApprovers(applicationIdIn => engAmeApplicationId,
5701                               transactionIdIn => engTransactionId,
5702                               transactionTypeIn => engTransactionTypeId,
5703                               approversOut => approversOut);
5704       exception
5705         when others then
5706           ame_util.runtimeException(packageNameIn => 'ame_engine',
5707                                     routineNameIn => 'getAllApprovers',
5708                                     exceptionNumberIn => sqlcode,
5709                                     exceptionStringIn => sqlerrm);
5710           raise;
5711     end getAllApprovers;
5712   procedure getApplicableRules
5713     (ruleIdsOut             out nocopy ame_util.idList
5714     ,ruleDescriptionsOut    out nocopy ame_util.stringList) as
5715     nextRuleIndex  integer;
5716     ruleFound      boolean;
5717     begin
5718       nextRuleIndex := 1;
5719       for i in 1 .. engAppRuleIds.count loop
5720         if engRuleAppliedYN(i) = ame_util.booleanTrue then
5721           if nextRuleIndex = 1 then
5722             ruleFound := false;
5723           else
5724             ruleFound := false;
5725             for j in 1 .. (nextRuleIndex - 1) loop
5726               if ruleIdsOut(j) = engAppRuleIds(i) then
5727                 ruleFound := true;
5728                 exit;
5729               end if;
5730             end loop;
5731           end if;
5732           if not ruleFound then
5733             ruleIdsOut(nextRuleIndex) := engAppRuleIds(i);
5734             ruleDescriptionsOut(nextRuleIndex) := ame_rule_pkg.getDescription(ruleIdIn => engAppRuleIds(i),
5735                                                                               processingDateIn => engEffectiveRuleDate);
5736             nextRuleIndex := nextRuleIndex + 1;
5737           end if;
5738         end if;
5739       end loop;
5740       exception
5741         when others then
5742           ame_util.runtimeException(packageNameIn => 'ame_engine',
5743                                     routineNameIn => 'getApplicableRules',
5744                                     exceptionNumberIn => sqlcode,
5745                                     exceptionStringIn => sqlerrm);
5746           raise;
5747     end getApplicableRules;
5748   /* BUG: 4491715 sort approver categories and sources along with group ids */
5749   procedure getApprovalGroupConfigs(groupIdsInOut in out nocopy ame_util.idList,
5750                                     sourcesInOut in out nocopy ame_util.longStringList,
5751                                     approverCategoriesInOut in out nocopy ame_util.charList,
5752                                     orderNumbersOut out nocopy ame_util.idList,
5753                                     votingRegimesOut out nocopy ame_util.charList) as
5754     cursor approvalGroupConfigCursor(groupIdIn in integer) is
5755       select
5756         order_number,
5757         voting_regime
5758         from ame_approval_group_config
5759         where
5760           application_id = engAmeApplicationId and
5761           approval_group_id = groupIdIn and
5762         engEffectiveRuleDate between
5763           start_date and
5764           nvl(end_date - ame_util.oneSecond, engEffectiveRuleDate);
5765     tempGroupId integer;
5766     tempOrderNumber integer;
5767     tempVotingRegime ame_util.charType;
5768     tempSource ame_util.longStringType;
5769     tempApproverCategory ame_util.charType;
5770     upperLimit integer;
5771     begin
5772       /*
5773         Evidently it's more efficient to fetch this way, than to do a single bulk fetch
5774         with a comma-delimited list of group IDs.
5775       */
5776       for i in 1 .. groupIdsInOut.count loop
5777         open approvalGroupConfigCursor(groupIdIn => groupIdsInOut(i));
5778         fetch approvalGroupConfigCursor
5779           into
5780             orderNumbersOut(i),
5781             votingRegimesOut(i);
5782         close approvalGroupConfigCursor;
5783       end loop;
5784       /* Sort in place, first by group order number, then by group ID. */
5785       for i in 2 .. groupIdsInOut.count loop
5786         upperLimit := i - 1;
5787         for j in 1 .. upperLimit loop
5788           if(orderNumbersOut(i) < orderNumbersOut(j) or
5789              (orderNumbersOut(i) = orderNumbersOut(j) and
5790               groupIdsInOut(i) < groupIdsInOut(j))) then
5791             /* j into temps */
5792             tempGroupId := groupIdsInOut(j);
5793             tempOrderNumber := orderNumbersOut(j);
5794             tempVotingRegime := votingRegimesOut(j);
5795             tempSource := sourcesInOut(j);
5796             tempApproverCategory := approverCategoriesInOut(j);
5797             /* i into j */
5798             groupIdsInOut(j) := groupIdsInOut(i);
5799             orderNumbersOut(j) := orderNumbersOut(i);
5800             votingRegimesOut(j) := votingRegimesOut(i);
5801             sourcesInOut(j) := sourcesInOut(i);
5802             approverCategoriesInOut(j) := approverCategoriesInOut(i);
5803             /* temps into i */
5804             groupIdsInOut(i) := tempGroupId;
5805             orderNumbersOut(i) := tempOrderNumber;
5806             votingRegimesOut(i) := tempVotingRegime;
5807             sourcesInOut(i) := tempSource;
5808             approverCategoriesInOut(i) := tempApproverCategory;
5809           end if;
5810         end loop;
5811       end loop;
5812       exception
5813         when others then
5814           if(approvalGroupConfigCursor%isopen) then
5815             close approvalGroupConfigCursor;
5816           end if;
5817           ame_util.runtimeException(packageNameIn => 'ame_engine',
5818                                     routineNameIn => 'getApprovalGroupConfigs',
5819                                     exceptionNumberIn => sqlcode,
5820                                     exceptionStringIn => sqlerrm);
5821           raise;
5822     end getApprovalGroupConfigs;
5823   procedure getApprovers(approversOut out nocopy ame_util.approversTable2) as
5824     begin
5825       if (not engItemDataPrepared) and engPrepareItemData then
5826         prepareItemData(itemIndexesOut     => engStItemIndexes
5827                        ,itemItemClassesOut => engStItemClasses
5828                        ,itemIdsOut         => engStItemIds
5829                        ,itemSourcesOut     => engStItemSources);
5830         engItemDataPrepared := true;
5831       end if;
5832       prepareRuleData;
5833       preparePerApproverProductions
5834            (prodIndexesOut      => engStProductionIndexes
5835            ,productionNamesOut  => engStVariableNames
5836            ,productionValuesOut => engStVariableValues);
5837       for i in 1 .. engStApprovers.count loop
5838         approversOut(i).name := engStApprovers(i).name;
5839         approversOut(i).orig_system := engStApprovers(i).orig_system;
5840         approversOut(i).orig_system_id := engStApprovers(i).orig_system_id;
5841         approversOut(i).display_name := engStApprovers(i).display_name;
5842         approversOut(i).approver_category := engStApprovers(i).approver_category;
5843         approversOut(i).api_insertion := engStApprovers(i).api_insertion;
5844         approversOut(i).authority := engStApprovers(i).authority;
5845         approversOut(i).approval_status := engStApprovers(i).approval_status;
5846         approversOut(i).action_type_id := engStApprovers(i).action_type_id;
5847         approversOut(i).group_or_chain_id := engStApprovers(i).group_or_chain_id;
5848         approversOut(i).occurrence := engStApprovers(i).occurrence;
5849         approversOut(i).source := engStApprovers(i).source;
5850         approversOut(i).item_class := engStApprovers(i).item_class;
5851         approversOut(i).item_id := engStApprovers(i).item_id;
5852         approversOut(i).item_class_order_number := engStApprovers(i).item_class_order_number;
5853         approversOut(i).item_order_number := engStApprovers(i).item_order_number;
5854         approversOut(i).sub_list_order_number := engStApprovers(i).sub_list_order_number;
5855         approversOut(i).action_type_order_number := engStApprovers(i).action_type_order_number;
5856         approversOut(i).group_or_chain_order_number := engStApprovers(i).group_or_chain_order_number;
5857         approversOut(i).member_order_number := engStApprovers(i).member_order_number;
5858         approversOut(i).approver_order_number := engStApprovers(i).approver_order_number;
5859       end loop;
5860       exception
5861         when others then
5862           ame_util.runtimeException(packageNameIn => 'ame_engine',
5863                                     routineNameIn => 'getApprovers',
5864                                     exceptionNumberIn => sqlcode,
5865                                     exceptionStringIn => sqlerrm);
5866           raise;
5867     end getApprovers;
5868   /* This procedure returns the approvers as well as approvers tree to the calling APIs */
5869   procedure getApprovers2(approversOut out nocopy ame_util.approversTable2
5870                          ,approversTreeOut out nocopy ame_util.approversTreeTable) as
5871     loopIndex integer;
5872     begin
5873       for i in 1 .. engStApprovers.count loop
5874         approversOut(i).name := engStApprovers(i).name;
5875         approversOut(i).orig_system := engStApprovers(i).orig_system;
5876         approversOut(i).orig_system_id := engStApprovers(i).orig_system_id;
5877         approversOut(i).display_name := engStApprovers(i).display_name;
5878         approversOut(i).approver_category := engStApprovers(i).approver_category;
5879         approversOut(i).api_insertion := engStApprovers(i).api_insertion;
5880         approversOut(i).authority := engStApprovers(i).authority;
5881         approversOut(i).approval_status := engStApprovers(i).approval_status;
5882         approversOut(i).action_type_id := engStApprovers(i).action_type_id;
5883         approversOut(i).group_or_chain_id := engStApprovers(i).group_or_chain_id;
5884         approversOut(i).occurrence := engStApprovers(i).occurrence;
5885         approversOut(i).source := engStApprovers(i).source;
5886         approversOut(i).item_class := engStApprovers(i).item_class;
5887         approversOut(i).item_id := engStApprovers(i).item_id;
5888         approversOut(i).item_class_order_number := engStApprovers(i).item_class_order_number;
5889         approversOut(i).item_order_number := engStApprovers(i).item_order_number;
5890         approversOut(i).sub_list_order_number := engStApprovers(i).sub_list_order_number;
5891         approversOut(i).action_type_order_number := engStApprovers(i).action_type_order_number;
5892         approversOut(i).group_or_chain_order_number := engStApprovers(i).group_or_chain_order_number;
5893         approversOut(i).member_order_number := engStApprovers(i).member_order_number;
5894         approversOut(i).approver_order_number := engStApprovers(i).approver_order_number;
5895       end loop;
5896       if engStApproversTree.count > 0 then
5897         /* Approvers Tree is sparse */
5898         loopIndex := engStApproversTree.first;
5899         loop
5900           approversTreeOut(loopIndex).parent_index   := engStApproversTree(loopIndex).parent_index;
5901           approversTreeOut(loopIndex).child_index    := engStApproversTree(loopIndex).child_index;
5902           approversTreeOut(loopIndex).sibling_index  := engStApproversTree(loopIndex).sibling_index;
5903           approversTreeOut(loopIndex).approver_index := engStApproversTree(loopIndex).approver_index;
5904           approversTreeOut(loopIndex).tree_level     := engStApproversTree(loopIndex).tree_level;
5905           approversTreeOut(loopIndex).tree_level_id  := engStApproversTree(loopIndex).tree_level_id;
5906           approversTreeOut(loopIndex).order_number   := engStApproversTree(loopIndex).order_number;
5907           approversTreeOut(loopIndex).min_order      := engStApproversTree(loopIndex).min_order;
5908           approversTreeOut(loopIndex).max_order      := engStApproversTree(loopIndex).max_order;
5909           approversTreeOut(loopIndex).status         := engStApproversTree(loopIndex).status;
5910           approversTreeOut(loopIndex).is_suspended   := engStApproversTree(loopIndex).is_suspended;
5911           exit when loopIndex = engStApproversTree.last;
5912           loopIndex := engStApproversTree.next(loopIndex);
5913         end loop;
5914       end if;
5915       exception
5916         when others then
5917           ame_util.runtimeException(packageNameIn => 'ame_engine',
5918                                     routineNameIn => 'getApprovers2',
5919                                     exceptionNumberIn => sqlcode,
5920                                     exceptionStringIn => sqlerrm);
5921           raise;
5922     end getApprovers2;
5923   procedure getHandlerCOAFirstApprover(itemClassIn in varchar2,
5924                                        itemIdIn in varchar2,
5925                                        actionTypeIdIn in integer,
5926                                        groupOrChainIdIn in integer,
5927                                        nameOut out nocopy varchar2,
5928                                        origSystemOut out nocopy varchar2,
5929                                        origSystemIdOut out nocopy integer,
5930                                        displayNameOut out nocopy varchar2,
5931                                        sourceOut out nocopy varchar2) as
5932     parameter ame_temp_insertions.parameter%type;
5933     begin
5934       parameter := ame_util.firstAuthorityParameter ||
5935                    ame_util.fieldDelimiter ||
5936                    itemClassIn ||
5937                    ame_util.fieldDelimiter ||
5938                    itemIdIn ||
5939                    ame_util.fieldDelimiter ||
5940                    actionTypeIdIn ||
5941                    ame_util.fieldDelimiter ||
5942                    groupOrChainIdIn;
5943       for i in 1 .. engInsertedApproverList.count loop
5944         if(engInsertionParameterList(i) = parameter) then
5945           nameOut := engInsertedApproverList(i).name;
5946           ame_approver_type_pkg.getOrigSystemIdAndDisplayName(nameIn => engInsertedApproverList(i).name,
5947                                                               origSystemOut => origSystemOut,
5948                                                               origSystemIdOut => origSystemIdOut,
5949                                                               displayNameOut => displayNameOut);
5950           sourceOut := ame_util.otherInsertion;
5951           setDeviationReasonDate(engInsertionReasonList(i),engInsertionDateList(i));
5952           return;
5953         end if;
5954       end loop;
5955       exception
5956         when others then
5957           ame_util.runtimeException(packageNameIn => 'ame_engine',
5958                                     routineNameIn => 'getHandlerCOAFirstApprover',
5959                                     exceptionNumberIn => sqlcode,
5960                                     exceptionStringIn => sqlerrm);
5961           raise;
5962     end getHandlerCOAFirstApprover;
5963   procedure getHandlerCOAInsertion(nameIn in varchar2,
5964                                    itemClassIn in varchar2,
5965                                    itemIdIn in varchar2,
5966                                    actionTypeIdIn in integer,
5967                                    groupOrChainIdIn in integer,
5968                                    occurrenceIn in integer,
5969                                    approvalStatusIn in varchar2,
5970                                    nameOut out nocopy varchar2,
5971                                    origSystemOut out nocopy varchar2,
5972                                    origSystemIdOut out nocopy integer,
5973                                    displayNameOut out nocopy varchar2,
5974                                    sourceOut out nocopy varchar2) as
5975     parameter ame_temp_insertions.parameter%type;
5976     begin
5977       parameter := nameIn ||
5978                    ame_util.fieldDelimiter ||
5979                    itemClassIn ||
5980                    ame_util.fieldDelimiter ||
5981                    itemIdIn ||
5982                    ame_util.fieldDelimiter ||
5983                    actionTypeIdIn ||
5984                    ame_util.fieldDelimiter ||
5985                    groupOrChainIdIn ||
5986                    ame_util.fieldDelimiter ||
5987                    occurrenceIn;
5988       for i in 1 .. engInsertedApproverList.count loop
5989         if(engInsertedApproverList(i).api_insertion = ame_util.apiAuthorityInsertion and
5990            engInsertionOrderTypeList(i) = ame_util.afterApprover and
5991            engInsertionParameterList(i) = parameter) then
5992           nameOut := engInsertedApproverList(i).name;
5993           ame_approver_type_pkg.getOrigSystemIdAndDisplayName(nameIn => engInsertedApproverList(i).name,
5994                                                               origSystemOut => origSystemOut,
5995                                                               origSystemIdOut => origSystemIdOut,
5996                                                               displayNameOut => displayNameOut);
5997           if(engInsertionIsSpecialForwardee(i) = ame_util.booleanTrue) then
5998             sourceOut := ame_util.specialForwardInsertion;
5999           elsif(approvalStatusIn = ame_util.forwardStatus) then
6000             sourceOut := ame_util.forwardInsertion;
6001           elsif(approvalStatusIn = ame_util.approveAndForwardStatus) then
6002             sourceOut := ame_util.approveAndForwardInsertion;
6003           else
6004             sourceOut := ame_util.otherInsertion;
6005           end if;
6006           setDeviationReasonDate(engInsertionReasonList(i),engInsertionDateList(i));
6007           return;
6008         end if;
6009       end loop;
6010       exception
6011         when others then
6012           ame_util.runtimeException(packageNameIn => 'ame_engine',
6013                                     routineNameIn => 'getHandlerCOAInsertion',
6014                                     exceptionNumberIn => sqlcode,
6015                                     exceptionStringIn => sqlerrm);
6016           raise;
6017     end getHandlerCOAInsertion;
6018   procedure getHandlerRules(ruleIdsOut out nocopy ame_util.idList,
6019                             approverCategoriesOut out nocopy ame_util.charList,
6020                             parametersOut out nocopy ame_util.stringList,
6021                             parameterTwosOut out nocopy ame_util.stringList) as
6022     outputIndex integer;
6023     begin
6024       outputIndex := 0;
6025       for i in engAppHandlerFirstIndex .. engAppHandlerLastIndex loop
6026         outputIndex := outputIndex + 1;
6027         ruleIdsOut(outputIndex) := engAppRuleIds(i);
6028         approverCategoriesOut(outputIndex) := engAppApproverCategories(i);
6029         parametersOut(outputIndex) := engAppParameters(i);
6030         parameterTwosOut(outputIndex) := engAppParameterTwos(i);
6031       end loop;
6032       exception
6033         when others then
6034           ame_util.runtimeException(packageNameIn => 'ame_engine',
6035                                     routineNameIn => 'getHandlerRules',
6036                                     exceptionNumberIn => sqlcode,
6037                                     exceptionStringIn => sqlerrm);
6038           raise;
6039     end getHandlerRules;
6040   procedure getHandlerRules2(ruleIdsOut out nocopy ame_util.idList,
6041                              approverCategoriesOut out nocopy ame_util.charList,
6042                              parametersOut out nocopy ame_util.stringList) as
6043     outputIndex integer;
6044     begin
6045       outputIndex := 0;
6046       for i in engAppHandlerFirstIndex .. engAppHandlerLastIndex loop
6047         outputIndex := outputIndex + 1;
6048         ruleIdsOut(outputIndex) := engAppRuleIds(i);
6049         approverCategoriesOut(outputIndex) := engAppApproverCategories(i);
6050         parametersOut(outputIndex) := engAppParameters(i);
6051       end loop;
6052       exception
6053         when others then
6054           ame_util.runtimeException(packageNameIn => 'ame_engine',
6055                                     routineNameIn => 'getHandlerRules2',
6056                                     exceptionNumberIn => sqlcode,
6057                                     exceptionStringIn => sqlerrm);
6058           raise;
6059     end getHandlerRules2;
6060   procedure getHandlerRules3(ruleIdsOut out nocopy ame_util.idList,
6061                              ruleIndexesOut out nocopy ame_util.idList,
6062                              parametersOut out nocopy ame_util.stringList,
6063                              listModParameterOnesOut out nocopy ame_util.stringList,
6064                              listModParameterTwosOut out nocopy ame_util.longStringList) as
6065     outputIndex integer;
6066     begin
6067       outputIndex := 0;
6068       for i in engAppHandlerFirstIndex .. engAppHandlerLastIndex loop
6069         outputIndex := outputIndex + 1;
6070         ruleIdsOut(outputIndex) := engAppRuleIds(i);
6071         ruleIndexesOut(outputIndex) := i;
6072         parametersOut(outputIndex) := engAppParameters(i);
6073         getLMCondition(ruleIdIn => engAppRuleIds(i),
6074                        parameterOneOut => listModParameterOnesOut(outputIndex),
6075                        parameterTwoOut => listModParameterTwosOut(outputIndex));
6076       end loop;
6077       exception
6078         when others then
6079           ame_util.runtimeException(packageNameIn => 'ame_engine',
6080                                     routineNameIn => 'getHandlerRules3',
6081                                     exceptionNumberIn => sqlcode,
6082                                     exceptionStringIn => sqlerrm);
6083           raise;
6084     end getHandlerRules3;
6085   procedure getHandlerLMApprovers(listModParameterOneIn in varchar2,
6086                                   listModParameterTwoIn in varchar2,
6087                                   includeFyiApproversIn in boolean,
6088                                   includeApprovalGroupsIn in boolean,
6089                                   returnForwardeesIn in boolean,
6090                                   approverIndexesOut out nocopy ame_util.idList,
6091                                   lastForwardeeIndexesOut out nocopy ame_util.idList) as
6092     currentActionTypeId integer;
6093     currentGroupOrChainId integer;
6094     currentIndex integer;
6095     currentTargetIndex integer;
6096     engStApproversCount integer;
6097     outputIndex integer;
6098     begin
6099       engStApproversCount := engStApprovers.count;
6100       if(engStApproversCount = 0) then
6101         return;
6102       end if;
6103       outputIndex := 0; /* pre-increment */
6104       currentIndex := 1; /* post-increment */
6105       loop
6106         if((engStApprovers(currentIndex).approver_category = ame_util.approvalApproverCategory or
6107             includeFyiApproversIn) and
6108            (engStApprovers(currentIndex).authority = ame_util.authorityApprover or
6109             includeApprovalGroupsIn) and
6110            listModParameterTwoIn = engStApprovers(currentIndex).name) then
6111           /* This approver matches the input approver, and satisfies the input boolean arguments. */
6112           currentTargetIndex := currentIndex;
6113           currentGroupOrChainId := engStApprovers(currentTargetIndex).group_or_chain_id;
6114           currentActionTypeId := engStApprovers(currentTargetIndex).action_type_id;
6115           if(returnForwardeesIn) then
6116             /*
6117               Set currentIndex to the index of the last of any subsequent forwardees.  Start the loop
6118               at the target to check whether the target forwards.  (Note that we necessarily stay
6119               in the same approval group or chain of authority as long as we're forwarding.)
6120             */
6121             for i in currentTargetIndex .. engStApproversCount loop
6122               if(engStApprovers(currentIndex).approval_status in (ame_util.forwardStatus,
6123                                                                   ame_util.approveAndForwardStatus)) then
6124                 currentIndex := i;
6125               else
6126                 exit;
6127               end if;
6128             end loop;
6129           end if;
6130           /*
6131             Now increment currentIndex to point to the approver after the target, or after the target's
6132             forwarding chain if necessary.  (This may point past the end of the list; check for that.)
6133             This also serves to increment currentIndex for the outer loop.
6134           */
6135           currentIndex := currentIndex + 1;
6136           /*
6137             If the target approver satisfies listModParameterOneIn, output the target approver and
6138             optionally the last forwardee.
6139           */
6140           /*
6141             All but the first of the conditions in the following if statement
6142             are for the ame_util.finalApprover case.
6143           */
6144           if(listModParameterOneIn = ame_util.anyApprover or
6145              currentIndex > engStApproversCount or
6146              engStApprovers(currentIndex).group_or_chain_id <> currentGroupOrChainId or
6147              engStApprovers(currentIndex).action_type_id <> currentActionTypeId or
6148              engStApprovers(currentIndex).item_id <> engStApprovers(currentTargetIndex).item_id or
6149              engStApprovers(currentIndex).item_class <> engStApprovers(currentTargetIndex).item_class) then
6150             /* Output the approver(s). */
6151             outputIndex := outputIndex + 1;
6152             approverIndexesOut(outputIndex) := currentTargetIndex;
6153             if(returnForwardeesIn) then
6154               lastForwardeeIndexesOut(outputIndex) := currentIndex - 1;
6155             end if;
6156           end if;
6157         else /* Just iterate. */
6158           currentIndex := currentIndex + 1;
6159         end if;
6160         /* Exit the loop upon reaching the end of engStApprovers. */
6161         if(currentIndex > engStApproversCount) then
6162           exit;
6163         end if;
6164       end loop;
6165       exception
6166         when others then
6167           ame_util.runtimeException(packageNameIn => 'ame_engine',
6168                                     routineNameIn => 'getHandlerLMApprovers',
6169                                     exceptionNumberIn => sqlcode,
6170                                     exceptionStringIn => sqlerrm);
6171           raise;
6172     end getHandlerLMApprovers;
6173   procedure getHeaderAttValues1(attributeIdIn in integer,
6174                                 attributeValue1Out out nocopy varchar2,
6175                                 attributeValue2Out out nocopy varchar2,
6176                                 attributeValue3Out out nocopy varchar2) as
6177     attributeValueIndex integer;
6178     begin
6179       attributeValueIndex := engAttributeValueIndexes(attributeIdIn);
6180       attributeValue1Out := engAttributeValues1(attributeValueIndex);
6181       attributeValue2Out := engAttributeValues2(attributeValueIndex);
6182       attributeValue3Out := engAttributeValues3(attributeValueIndex);
6183       exception
6184         when others then
6185           ame_util.runtimeException(packageNameIn => 'ame_engine',
6186                                     routineNameIn => 'getHeaderAttValues1',
6187                                     exceptionNumberIn => sqlcode,
6188                                     exceptionStringIn => sqlerrm);
6189           raise;
6190     end getHeaderAttValues1;
6191   procedure getHeaderAttValues2(attributeNameIn in varchar2,
6192                                 attributeValue1Out out nocopy varchar2,
6193                                 attributeValue2Out out nocopy varchar2,
6194                                 attributeValue3Out out nocopy varchar2) as
6195     attributeValueIndex integer;
6196     begin
6197       if (engAttributeVariant.exists(getAttributeIdByName(attributeNameIn => attributeNameIn))) then
6198         /* fetch the new attribute value */
6199         attributeValue1Out := getVariantAttributeValue(attributeIdIn => getAttributeIdByName(attributeNameIn => attributeNameIn),
6200                                     itemClassIn => getItemClassName(itemClassIdIn => engAppRuleItemClassIds(engAppHandlerFirstIndex)),
6201                                     itemIdIn => engAppAppItemIds(engAppHandlerFirstIndex) );
6202         attributeValue2Out := null;
6203         attributeValue3Out := null;
6204       else
6205         attributeValueIndex := engAttributeValueIndexes(getAttributeIdByName(attributeNameIn => attributeNameIn));
6206         attributeValue1Out := engAttributeValues1(attributeValueIndex);
6207         attributeValue2Out := engAttributeValues2(attributeValueIndex);
6208         attributeValue3Out := engAttributeValues3(attributeValueIndex);
6209       end if;
6210       exception
6211         when others then
6212           ame_util.runtimeException(packageNameIn => 'ame_engine',
6213                                     routineNameIn => 'getHeaderAttValues2',
6214                                     exceptionNumberIn => sqlcode,
6215                                     exceptionStringIn => sqlerrm);
6216           raise;
6217     end getHeaderAttValues2;
6218   procedure getItemAppProcessCompleteYN(itemAppProcessCompleteYNOut out nocopy ame_util.charList) as
6219     begin
6220       for i in 1 .. engStItemAppProcessCompleteYN.count loop
6221         itemAppProcessCompleteYNOut(i) := engStItemAppProcessCompleteYN(i);
6222       end loop;
6223       exception
6224         when others then
6225           ame_util.runtimeException(packageNameIn => 'ame_engine',
6226                                     routineNameIn => 'getItemAppProcessCompleteYN',
6227                                     exceptionNumberIn => sqlcode,
6228                                     exceptionStringIn => sqlerrm);
6229           raise;
6230     end getItemAppProcessCompleteYN;
6231   procedure getItemAttValues1(attributeIdIn in integer,
6232                               itemIdIn in varchar2,
6233                               attributeValue1Out out nocopy varchar2,
6234                               attributeValue2Out out nocopy varchar2,
6235                               attributeValue3Out out nocopy varchar2) as
6236     attributeValueIndex integer;
6237     begin
6238       attributeValueIndex :=
6239         engAttributeValueIndexes(attributeIdIn) +
6240         getItemOffset(itemClassIdIn => engAttributeItemClassIds(attributeIdIn),
6241                       itemIdIn => itemIdIn);
6242       attributeValue1Out := engAttributeValues1(attributeValueIndex);
6243       attributeValue2Out := engAttributeValues2(attributeValueIndex);
6244       attributeValue3Out := engAttributeValues3(attributeValueIndex);
6245       exception
6246         when others then
6247           ame_util.runtimeException(packageNameIn => 'ame_engine',
6248                                     routineNameIn => 'getItemAttValues1',
6249                                     exceptionNumberIn => sqlcode,
6250                                     exceptionStringIn => sqlerrm);
6251           raise;
6252     end getItemAttValues1;
6253   procedure getItemAttValues2(attributeNameIn in varchar2,
6254                               itemIdIn in varchar2,
6255                               attributeValue1Out out nocopy varchar2,
6256                               attributeValue2Out out nocopy varchar2,
6257                               attributeValue3Out out nocopy varchar2) as
6258     attributeId integer;
6259     attributeValueIndex integer;
6260     begin
6261       attributeId := getAttributeIdByName(attributeNameIn => attributeNameIn);
6262       attributeValueIndex :=
6263         engAttributeValueIndexes(attributeId) +
6264         getItemOffset(itemClassIdIn => engAttributeItemClassIds(attributeId),
6265                       itemIdIn => itemIdIn);
6266       attributeValue1Out := engAttributeValues1(attributeValueIndex);
6267       attributeValue2Out := engAttributeValues2(attributeValueIndex);
6268       attributeValue3Out := engAttributeValues3(attributeValueIndex);
6269       exception
6270         when others then
6271           ame_util.runtimeException(packageNameIn => 'ame_engine',
6272                                     routineNameIn => 'getItemAttValues2',
6273                                     exceptionNumberIn => sqlcode,
6274                                     exceptionStringIn => sqlerrm);
6275           raise;
6276     end getItemAttValues2;
6277   procedure getItemAttValues3(attributeIdIn in integer,
6278                               itemIndexIn in varchar2,
6279                               attributeValue1Out out nocopy varchar2,
6280                               attributeValue2Out out nocopy varchar2,
6281                               attributeValue3Out out nocopy varchar2) as
6282     attributeValueIndex integer;
6283     begin
6284       attributeValueIndex :=
6285         engAttributeValueIndexes(attributeIdIn) +
6286         itemIndexIn -
6287         engItemClassItemIdIndexes(engItemClassIndexes(engAttributeItemClassIds(attributeIdIn)));
6288       attributeValue1Out := engAttributeValues1(attributeValueIndex);
6289       attributeValue2Out := engAttributeValues2(attributeValueIndex);
6290       attributeValue3Out := engAttributeValues3(attributeValueIndex);
6291       exception
6292         when others then
6293           ame_util.runtimeException(packageNameIn => 'ame_engine',
6294                                     routineNameIn => 'getItemAttValues3',
6295                                     exceptionNumberIn => sqlcode,
6296                                     exceptionStringIn => sqlerrm);
6297           raise;
6298     end getItemAttValues3;
6299   procedure getItemClassAttValues1(attributeIdIn in integer,
6300                                    attributeValuesOut out nocopy ame_util.attributeValueList) as
6301     outputIndex integer;
6302     begin
6303       outputIndex := 0; /* pre-increment */
6304       for i in
6305         engAttributeValueIndexes(attributeIdIn) ..
6306         (engAttributeValueIndexes(attributeIdIn) +
6307          engItemCounts(engItemClassIndexes(engAttributeItemClassIds(attributeIdIn))) -
6308          1) loop
6309         outputIndex := outputIndex + 1;
6310         attributeValuesOut(outputIndex) := engAttributeValues1(i);
6311       end loop;
6312       exception
6313         when others then
6314           ame_util.runtimeException(packageNameIn => 'ame_engine',
6315                                     routineNameIn => 'getItemClassAttValues1',
6316                                     exceptionNumberIn => sqlcode,
6317                                     exceptionStringIn => sqlerrm);
6318           raise;
6319     end getItemClassAttValues1;
6320   procedure getItemClassAttValues2(attributeNameIn in varchar2,
6321                                    attributeValuesOut out nocopy ame_util.attributeValueList) as
6322     attributeId integer;
6323     outputIndex integer;
6324     begin
6325       attributeId := getAttributeIdByName(attributeNameIn => attributeNameIn);
6326       outputIndex := 0; /* pre-increment */
6327       for i in
6328         engAttributeValueIndexes(attributeId) ..
6329         (engAttributeValueIndexes(attributeId) +
6330          engItemCounts(engItemClassIndexes(engAttributeItemClassIds(attributeId))) -
6331          1) loop
6332         outputIndex := outputIndex + 1;
6333         attributeValuesOut(outputIndex) := engAttributeValues1(i);
6334       end loop;
6335       exception
6336         when others then
6337           ame_util.runtimeException(packageNameIn => 'ame_engine',
6338                                     routineNameIn => 'getItemClassAttValues2',
6339                                     exceptionNumberIn => sqlcode,
6340                                     exceptionStringIn => sqlerrm);
6341           raise;
6342     end getItemClassAttValues2;
6343   procedure getItemClassAttValues3(attributeIdIn in integer,
6344                                    attributeValues1Out out nocopy ame_util.attributeValueList,
6345                                    attributeValues2Out out nocopy ame_util.attributeValueList,
6346                                    attributeValues3Out out nocopy ame_util.attributeValueList) as
6347     outputIndex integer;
6348     begin
6349       outputIndex := 0; /* pre-increment */
6350       for i in
6351         engAttributeValueIndexes(attributeIdIn) ..
6352         (engAttributeValueIndexes(attributeIdIn) +
6353          engItemCounts(engItemClassIndexes(engAttributeItemClassIds(attributeIdIn))) -
6354          1) loop
6355         outputIndex := outputIndex + 1;
6356         attributeValues1Out(outputIndex) := engAttributeValues1(i);
6357         attributeValues2Out(outputIndex) := engAttributeValues2(i);
6358         attributeValues3Out(outputIndex) := engAttributeValues3(i);
6359       end loop;
6360       exception
6361         when others then
6362           ame_util.runtimeException(packageNameIn => 'ame_engine',
6363                                     routineNameIn => 'getItemClassAttValues3',
6364                                     exceptionNumberIn => sqlcode,
6365                                     exceptionStringIn => sqlerrm);
6366           raise;
6367     end getItemClassAttValues3;
6368   procedure getItemClassAttValues4(attributeNameIn in varchar2,
6369                                    attributeValues1Out out nocopy ame_util.attributeValueList,
6370                                    attributeValues2Out out nocopy ame_util.attributeValueList,
6371                                    attributeValues3Out out nocopy ame_util.attributeValueList) as
6372     attributeId integer;
6373     outputIndex integer;
6374     begin
6375       attributeId := getAttributeIdByName(attributeNameIn => attributeNameIn);
6376       outputIndex := 0; /* pre-increment */
6377       for i in
6378         engAttributeValueIndexes(attributeId) ..
6379         (engAttributeValueIndexes(attributeId) +
6380          engItemCounts(engItemClassIndexes(engAttributeItemClassIds(attributeId))) -
6381          1) loop
6382         outputIndex := outputIndex + 1;
6383         attributeValues1Out(outputIndex) := engAttributeValues1(i);
6384         attributeValues2Out(outputIndex) := engAttributeValues2(i);
6385         attributeValues3Out(outputIndex) := engAttributeValues3(i);
6386       end loop;
6387       exception
6388         when others then
6389           ame_util.runtimeException(packageNameIn => 'ame_engine',
6390                                     routineNameIn => 'getItemClassAttValues4',
6391                                     exceptionNumberIn => sqlcode,
6392                                     exceptionStringIn => sqlerrm);
6393           raise;
6394     end getItemClassAttValues4;
6395   procedure getItemClassItemIds(itemClassIdIn in integer,
6396                                 itemIdsOut out nocopy ame_util.stringList) as
6397     firstItemIndex integer;
6398     itemClassIndex integer;
6399     tempIndex integer;
6400     begin
6401       itemClassIndex := engItemClassIndexes(itemClassIdIn);
6402       firstItemIndex := engItemClassItemIdIndexes(itemClassIndex);
6403       if(firstItemIndex is not null) then
6404         tempIndex := 0; /* pre-increment */
6405         for itemIndex in
6406           firstItemIndex ..
6407           (firstItemIndex + engItemCounts(itemClassIndex) - 1) loop
6408           tempIndex := tempIndex + 1;
6409           itemIdsOut(tempIndex) := engItemIds(itemIndex);
6410         end loop;
6411       end if;
6412       exception
6413         when others then
6414           itemIdsOut.delete;
6415           ame_util.runtimeException(packageNameIn => 'ame_engine',
6416                                     routineNameIn => 'getItemClassItemIds',
6417                                     exceptionNumberIn => sqlcode,
6418                                     exceptionStringIn => sqlerrm);
6419           raise;
6420     end getItemClassItemIds;
6421   procedure getItemClasses(itemClassesOut out nocopy ame_util.stringList) as
6422     begin
6423       for i in 1 .. engStItemClasses.count loop
6424         itemClassesOut(i) := engStItemClasses(i);
6425       end loop;
6426       exception
6427         when others then
6428           ame_util.runtimeException(packageNameIn => 'ame_engine',
6429                                     routineNameIn => 'getItemClasses',
6430                                     exceptionNumberIn => sqlcode,
6431                                     exceptionStringIn => sqlerrm);
6432           raise;
6433     end getItemClasses;
6434   procedure getItemIds(itemIdsOut out nocopy ame_util.stringList) as
6435     begin
6436       for i in 1 .. engStItemIds.count loop
6437         itemIdsOut(i) := engStItemIds(i);
6438       end loop;
6439       exception
6440         when others then
6441           ame_util.runtimeException(packageNameIn => 'ame_engine',
6442                                     routineNameIn => 'getItemIds',
6443                                     exceptionNumberIn => sqlcode,
6444                                     exceptionStringIn => sqlerrm);
6445           raise;
6446     end getItemIds;
6447   procedure getItemIndexes(itemIndexesOut out nocopy ame_util.idList) as
6448     begin
6449       for i in 1 .. engStItemIndexes.count loop
6450         itemIndexesOut(i) := engStItemIndexes(i);
6451       end loop;
6452       exception
6453         when others then
6454           ame_util.runtimeException(packageNameIn => 'ame_engine',
6455                                     routineNameIn => 'getItemIndexes',
6456                                     exceptionNumberIn => sqlcode,
6457                                     exceptionStringIn => sqlerrm);
6458           raise;
6459     end getItemIndexes;
6460   procedure getItemSources(itemSourcesOut out nocopy ame_util.longStringList) as
6461     begin
6462       for i in 1 .. engStItemSources.count loop
6463         itemSourcesOut(i) := engStItemSources(i);
6464       end loop;
6465       exception
6466         when others then
6467           ame_util.runtimeException(packageNameIn => 'ame_engine',
6468                                     routineNameIn => 'getItemSources',
6469                                     exceptionNumberIn => sqlcode,
6470                                     exceptionStringIn => sqlerrm);
6471           raise;
6472     end getItemSources;
6473   procedure getAllItemClasses(itemClassNamesOut out nocopy ame_util.stringList) as
6474     tempIndex integer;
6475     tempCount integer;
6476     begin
6477       tempIndex := 0;
6478       tempCount := 0;
6479       for i in 1 .. engItemClassIds.count loop
6480         tempCount := engItemCounts(engItemClassIndexes(engItemClassIds(i)));
6481         tempIndex := itemClassNamesOut.count;
6482         for x in 1 .. tempCount loop
6483           itemClassNamesOut(tempIndex + x) := engItemClassNames(i);
6484         end loop;
6485       end loop;
6486       exception
6487         when others then
6488           ame_util.runtimeException(packageNameIn => 'ame_engine',
6489                                     routineNameIn => 'getAllItemClasses',
6490                                     exceptionNumberIn => sqlcode,
6491                                     exceptionStringIn => sqlerrm);
6492           raise;
6493     end getAllItemClasses;
6494   procedure getAllItemIds(itemIdsOut out nocopy ame_util.stringList) as
6495     begin
6496       for i in 1 .. engItemIds.count loop
6497         itemIdsOut(i) := engItemIds(i);
6498       end loop;
6499       exception
6500         when others then
6501           ame_util.runtimeException(packageNameIn => 'ame_engine',
6502                                     routineNameIn => 'getAllItemIds',
6503                                     exceptionNumberIn => sqlcode,
6504                                     exceptionStringIn => sqlerrm);
6505           raise;
6506     end getAllItemIds;
6507   procedure getInsertions
6508     (positionIn             in            number
6509     ,orderTypeIn            in            varchar2 default null
6510     ,coaInsertionsYNIn      in            varchar2 default ame_util.booleanTrue
6511     ,availableInsertionsOut    out nocopy ame_util.insertionsTable2
6512     ) as
6513 
6514     engStApproversCount         integer;
6515     availableInsertionsIndex    integer; /* pre-increment */
6516     errorCode                   integer;
6517     errorMessage                ame_util.longestStringType;
6518     invalidPositionException    exception;
6519     nextApproverDescription     varchar2(100);
6520     prevApproverDescription     varchar2(100);
6521     ruleIdList                  ame_util.idList;
6522     sourceDescription           ame_util.stringType;
6523     tempBoolean                 boolean;
6524     tempInsertionDoesNotExist   boolean;
6525     tempParameter               ame_temp_insertions.parameter%type;
6526   begin
6527 
6528     engStApproversCount := engStApprovers.count;
6529 
6530     if(positionIn < 1 or
6531        positionIn > engStApproversCount + 1 or
6532        not ame_util.isANonNegativeInteger(stringIn => positionIn)) then
6533       raise invalidPositionException;
6534     end if;
6535 
6536     availableInsertionsIndex := 0;
6537 
6538     if (orderTypeIn is null or
6539         orderTypeIn = ame_util.absoluteOrder) then
6540 
6541       tempParameter := positionIn;
6542       if (engStApproversCount = 0) then
6543 
6544         /* pre-approver */
6545         if (not ame_engine.insertionExists
6546                   (orderTypeIn   => ame_util.absoluteOrder
6547                   ,parameterIn   => tempParameter
6548                   )) then
6549           availableInsertionsIndex := availableInsertionsIndex + 1;
6550           availableInsertionsOut(availableInsertionsIndex).item_class := ame_util.headerItemClassName;
6551           availableInsertionsOut(availableInsertionsIndex).item_id := engTransactionId;
6552           availableInsertionsOut(availableInsertionsIndex).action_type_id := null;
6553           availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := null;
6554           availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.absoluteOrder;
6555           availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
6556           availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
6557           availableInsertionsOut(availableInsertionsIndex).authority := ame_util.preApprover;
6558           availableInsertionsOut(availableInsertionsIndex).description :=
6559                                         ame_util.absoluteOrderDescription || positionIn || '.  ';
6560         end if;
6561 
6562         /* authority approver */
6563         if (not ame_engine.insertionExists
6564                   (orderTypeIn   => ame_util.absoluteOrder
6565                   ,parameterIn   => tempParameter
6566                   )) then
6567           availableInsertionsIndex := availableInsertionsIndex + 1;
6568           availableInsertionsOut(availableInsertionsIndex).item_class := ame_util.headerItemClassName;
6569           availableInsertionsOut(availableInsertionsIndex).item_id := engTransactionId;
6570           availableInsertionsOut(availableInsertionsIndex).action_type_id := null;
6571           availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := null;
6572           availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.absoluteOrder;
6573           availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
6574           availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
6575           availableInsertionsOut(availableInsertionsIndex).authority := ame_util.authorityApprover;
6576           availableInsertionsOut(availableInsertionsIndex).description :=
6577                                          ame_util.absoluteOrderDescription || positionIn || '.  ';
6578         end if;
6579 
6580         /* post approver */
6581         if (not ame_engine.insertionExists
6582                   (orderTypeIn   => ame_util.absoluteOrder
6583                   ,parameterIn   => tempParameter
6584                   )) then
6585           availableInsertionsIndex := availableInsertionsIndex + 1;
6586           availableInsertionsOut(availableInsertionsIndex).item_class := ame_util.headerItemClassName;
6587           availableInsertionsOut(availableInsertionsIndex).item_id := engTransactionId;
6588           availableInsertionsOut(availableInsertionsIndex).action_type_id := null;
6589           availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := null;
6590           availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.absoluteOrder;
6591           availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
6592           availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
6593           availableInsertionsOut(availableInsertionsIndex).authority := ame_util.postApprover;
6594           availableInsertionsOut(availableInsertionsIndex).description :=
6595                                          ame_util.absoluteOrderDescription || positionIn || '.  ';
6596         end if;
6597 
6598       else /* If approver count is more than zero */
6599 
6600         if (positionIn < engStApproversCount + 1) then
6601 
6602           /* Attribute to the insertee the relevant properties of the approver at positionIn. */
6603           if (not ame_engine.insertionExists
6604                     (orderTypeIn   => ame_util.absoluteOrder
6605                     ,parameterIn   => tempParameter
6606                     )) then
6607             availableInsertionsIndex := availableInsertionsIndex + 1;
6608             availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn).item_class;
6609             availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn).item_id;
6610             availableInsertionsOut(availableInsertionsIndex).action_type_id := engStApprovers(positionIn).action_type_id;
6611             availableInsertionsOut(availableInsertionsIndex).group_or_chain_id :=
6612                                                                        engStApprovers(positionIn).group_or_chain_id;
6613             availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.absoluteOrder;
6614             availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
6615             availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
6616             availableInsertionsOut(availableInsertionsIndex).authority := engStApprovers(positionIn).authority;
6617             availableInsertionsOut(availableInsertionsIndex).description :=
6618                                          ame_util.absoluteOrderDescription || positionIn || '.  ';
6619           end if;
6620 
6621         end if;
6622 
6623         /*
6624           If there is an approver at positionIn - 1, and the approver's relevant properties differ from
6625           those of the approver at positionIn (if any), add a second available insertion, attributing
6626           to the insertee the relevant properties of engStApprovers(positionIn - 1).
6627         */
6628         if (positionIn = engStApproversCount + 1 or
6629             (positionIn > 1 and
6630              (engStApprovers(positionIn).group_or_chain_id <> engStApprovers(positionIn - 1).group_or_chain_id or
6631               engStApprovers(positionIn).action_type_id <> engStApprovers(positionIn - 1).action_type_id or
6632               engStApprovers(positionIn).item_id <> engStApprovers(positionIn - 1).item_id or
6633               engStApprovers(positionIn).item_class <> engStApprovers(positionIn - 1).item_class
6634              ))) then
6635 
6636           /* Attribute to the insertee the relevant properties of the approver at positionIn - 1. */
6637           if (not ame_engine.insertionExists
6638                     (orderTypeIn   => ame_util.absoluteOrder
6639                     ,parameterIn   => tempParameter
6640                     )) then
6641             availableInsertionsIndex := availableInsertionsIndex + 1;
6642             availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn - 1).item_class;
6643             availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn - 1).item_id;
6644             availableInsertionsOut(availableInsertionsIndex).action_type_id :=
6645                                                                    engStApprovers(positionIn - 1).action_type_id;
6646             availableInsertionsOut(availableInsertionsIndex).group_or_chain_id :=
6647                                                                  engStApprovers(positionIn - 1).group_or_chain_id;
6648             availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.absoluteOrder;
6649             availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
6650             availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
6651             availableInsertionsOut(availableInsertionsIndex).authority := engStApprovers(positionIn - 1).authority;
6652             availableInsertionsOut(availableInsertionsIndex).description :=
6653                                                     ame_util.absoluteOrderDescription || positionIn || '.  ';
6654           end if;
6655         end if;
6656       end if; /* End if approver count > 0 */
6657 
6658     end if; /* End if order type is absolute Order */
6659 
6660     /*
6661       ORDER TYPE:  afterApprover
6662       Ad-hoc afterApprover is available if positionIn > 1.  COA afterApprover is available if also
6663       the approver at positionIn - 1 is a COA approvalApproverCategory approver.
6664     */
6665     if (orderTypeIn is null or
6666         orderTypeIn = ame_util.afterApprover) then
6667 
6668       if (positionIn = 1 or
6669           engStApproversCount = 0) then
6670         prevApproverDescription := null;
6671       else
6672         prevApproverDescription :=
6673              ame_approver_type_pkg.getApproverDisplayName(nameIn => engStApprovers(positionIn - 1).name);
6674       end if;
6675 
6676       if(positionIn > 1) then /* ad-hoc */
6677 
6678         tempParameter := engStApprovers(positionIn - 1).name ||
6679                          ame_util.fieldDelimiter ||
6680                          engStApprovers(positionIn - 1).item_class ||
6681                          ame_util.fieldDelimiter ||
6682                          engStApprovers(positionIn - 1).item_id ||
6683                          ame_util.fieldDelimiter ||
6684                          engStApprovers(positionIn - 1).action_type_id ||
6685                          ame_util.fieldDelimiter ||
6686                          engStApprovers(positionIn - 1).group_or_chain_id ||
6687                          ame_util.fieldDelimiter ||
6688                          engStApprovers(positionIn - 1).occurrence;
6689 
6690         if (not ame_engine.insertionExists
6691                   (orderTypeIn   => ame_util.afterApprover
6692                   ,parameterIn   => tempParameter
6693                   )) then
6694           availableInsertionsIndex := availableInsertionsIndex + 1;
6695           availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn - 1).item_class;
6696           availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn - 1).item_id;
6697           availableInsertionsOut(availableInsertionsIndex).action_type_id :=
6698                                                                 engStApprovers(positionIn - 1).action_type_id;
6699           availableInsertionsOut(availableInsertionsIndex).group_or_chain_id :=
6700                                                              engStApprovers(positionIn - 1).group_or_chain_id;
6701           availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.afterApprover;
6702           availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
6703           availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
6704           availableInsertionsOut(availableInsertionsIndex).authority := engStApprovers(positionIn - 1).authority;
6705           availableInsertionsOut(availableInsertionsIndex).description :=
6706                                            ame_util.afterApproverDescription || prevApproverDescription;
6707         end if;
6708 
6709         if positionIn <= engStApproversCount then
6710 
6711           if (engStApprovers(positionIn).authority = ame_util.authorityApprover and
6712               engStApprovers(positionIn).api_insertion <> ame_util.apiInsertion and
6713               engStApprovers(positionIn).approver_category = ame_util.approvalApproverCategory and
6714               coaInsertionsYNIn = ame_util.booleanTrue and
6715               (not ame_engine.insertionExists
6716                    (orderTypeIn   => ame_util.afterApprover
6717                    ,parameterIn   => tempParameter
6718                    ))) then /* COA */
6719             availableInsertionsIndex := availableInsertionsIndex + 1;
6720             availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn - 1).item_class;
6721             availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn - 1).item_id;
6722             availableInsertionsOut(availableInsertionsIndex).action_type_id :=
6723                                                              engStApprovers(positionIn - 1).action_type_id;
6724             availableInsertionsOut(availableInsertionsIndex).group_or_chain_id :=
6725                                                                  engStApprovers(positionIn - 1).group_or_chain_id;
6726             availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.afterApprover;
6727               /* We've already build the parameter field above, let's not repeat the work here. */
6728             availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
6729             availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiAuthorityInsertion;
6730             availableInsertionsOut(availableInsertionsIndex).authority := engStApprovers(positionIn - 1).authority;
6731             availableInsertionsOut(availableInsertionsIndex).description :=
6732                                          ame_util.afterApproverDescription || prevApproverDescription;
6733           end if;
6734         end if;
6735       end if;
6736     end if;
6737 
6738     /*
6739       ORDER TYPE:  beforeApprover
6740       beforeApprover is available if engStApproversCount > 0 and positionIn < engStApproversCount + 1.
6741     */
6742     if (orderTypeIn is null or
6743          orderTypeIn = ame_util.beforeApprover
6744        ) then
6745 
6746       if (positionIn = engStApproversCount + 1 or
6747           engStApproversCount = 0) then
6748         nextApproverDescription := null;
6749       else
6750         nextApproverDescription :=
6751                  ame_approver_type_pkg.getApproverDisplayName(nameIn => engStApprovers(positionIn).name);
6752       end if;
6753 
6754       if (engStApproversCount > 0 and
6755           positionIn < engStApproversCount + 1) then
6756 
6757         tempParameter := engStApprovers(positionIn).name ||
6758                          ame_util.fieldDelimiter ||
6759                          engStApprovers(positionIn).item_class ||
6760                          ame_util.fieldDelimiter ||
6761                          engStApprovers(positionIn).item_id ||
6762                          ame_util.fieldDelimiter ||
6763                          engStApprovers(positionIn).action_type_id ||
6764                          ame_util.fieldDelimiter ||
6765                          engStApprovers(positionIn).group_or_chain_id ||
6766                          ame_util.fieldDelimiter ||
6767                          engStApprovers(positionIn).occurrence;
6768 
6769         if (not ame_engine.insertionExists
6770                   (orderTypeIn   => ame_util.beforeApprover
6771                   ,parameterIn   => tempParameter
6772                   )) then
6773           availableInsertionsIndex := availableInsertionsIndex + 1;
6774           availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn).item_class;
6775           availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn).item_id;
6776           availableInsertionsOut(availableInsertionsIndex).action_type_id := engStApprovers(positionIn).action_type_id;
6777           availableInsertionsOut(availableInsertionsIndex).group_or_chain_id :=
6778                                                                     engStApprovers(positionIn).group_or_chain_id;
6779           availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.beforeApprover;
6780           availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
6781           availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
6782           availableInsertionsOut(availableInsertionsIndex).authority := engStApprovers(positionIn).authority;
6783           availableInsertionsOut(availableInsertionsIndex).description :=
6784                                              ame_util.beforeApproverDescription || nextApproverDescription;
6785         end if;
6786       end if;
6787     end if;
6788 
6789     /*
6790       ORDER TYPE:  firstAuthority
6791       firstAuthority is available if the approver you're at is the first COA approver in a chain.
6792     */
6793     if (coaInsertionsYNIn = ame_util.booleanTrue and
6794         (orderTypeIn is null or
6795         orderTypeIn = ame_util.firstAuthority)) then
6796 
6797       if (positionIn < engStApproversCount + 1 and
6798           engStApprovers(positionIn).authority = ame_util.authorityApprover and
6799           engStApprovers(positionIn).api_insertion <> ame_util.apiInsertion) then
6800         tempBoolean := true; /* tempBoolean remains true if no previous authority is found. */
6801         for i in reverse 1..positionIn - 1 loop
6802           if (engStApprovers(i).group_or_chain_id <> engStApprovers(positionIn).group_or_chain_id or
6803               engStApprovers(i).action_type_id <> engStApprovers(positionIn).action_type_id or
6804               engStApprovers(i).item_id <> engStApprovers(positionIn).item_id or
6805               engStApprovers(i).item_class <> engStApprovers(positionIn).item_class) then
6806             exit;
6807           end if;
6808 
6809           if (engStApprovers(i).authority = ame_util.authorityApprover and
6810               engStApprovers(i).api_insertion <> ame_util.apiInsertion) then
6811             tempBoolean := false;
6812             exit;
6813           end if;
6814         end loop;
6815 
6816         if (tempBoolean) then
6817           tempParameter := ame_util.firstAuthorityParameter ||
6818                            ame_util.fieldDelimiter ||
6819                            engStApprovers(positionIn).item_class ||
6820                            ame_util.fieldDelimiter ||
6821                            engStApprovers(positionIn).item_id ||
6822                            ame_util.fieldDelimiter ||
6823                            engStApprovers(positionIn).action_type_id ||
6824                            ame_util.fieldDelimiter ||
6825                            engStApprovers(positionIn).group_or_chain_id;
6826 
6827           if (not ame_engine.insertionExists
6828                     (orderTypeIn   => ame_util.firstAuthority
6829                     ,parameterIn   => tempParameter
6830                     )) then
6831             availableInsertionsIndex := availableInsertionsIndex + 1;
6832             availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn).item_class;
6833             availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn).item_id;
6834             availableInsertionsOut(availableInsertionsIndex).action_type_id :=
6835                                                                    engStApprovers(positionIn).action_type_id;
6836             availableInsertionsOut(availableInsertionsIndex).group_or_chain_id :=
6837                                                                  engStApprovers(positionIn).group_or_chain_id;
6838             availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.firstAuthority;
6839             availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
6840             availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiAuthorityInsertion;
6841             availableInsertionsOut(availableInsertionsIndex).authority := ame_util.authorityApprover;
6842             availableInsertionsOut(availableInsertionsIndex).description := ame_util.firstAuthorityDescription;
6843           end if;
6844         end if;
6845       end if;
6846     end if;
6847 
6848     /*
6849       ORDER TYPE:  firstPostApprover
6850       Assume that in the case of an entirely empty approver list, we allow insertion of a first
6851       post-approver into the header item's list only.  Otherwise, we only allow insertion of a
6852       first post-approver into a non-empty item list.  Here is the case analysis:
6853           if(the approver list is empty) then
6854             allow a first-post-approver insertion for the header
6855           elsif(positionIn is after the end of the approver list) then
6856             if(the last approver in the list is not a post-approver) then
6857               allow a first-post-approver insertion for the last approver's item
6858             end if
6859           elsif(positionIn = 1) then
6860             if(the first approver in the list is a post-approver_ then
6861               allow a first-post-approver insertion for the first approver's item
6862             end if
6863           else
6864             if(the engStApprovers at positionIn - 1 and positionIn are for the same item) then
6865               if(the first approver is not a post-approver and
6866                  the second approver is a post-approver) then
6867                 allow a first-post-approver insertion for the engStApprovers' item
6868               end if
6869             else
6870               if(the second approver is a post-approver) then
6871                 allow a first-post-approver insertion for the second approver's item
6872               end if
6873               if(the first approver is not a post-approver) then
6874                 allow a first-post-approver insertion for the first approver's item
6875               end if
6876             end if
6877           end if
6878     */
6879     if (orderTypeIn is null or
6880         orderTypeIn = ame_util.firstPostApprover) then
6881 
6882       if (engStApproversCount = 0) then
6883         tempParameter := ame_util.firstPostParameter ||
6884                          ame_util.fieldDelimiter ||
6885                          ame_util.headerItemClassName ||
6886                          ame_util.fieldDelimiter ||
6887                          engTransactionId;
6888 
6889         if (not ame_engine.insertionExists
6890                   (orderTypeIn => ame_util.firstPostApprover
6891                   ,parameterIn => tempParameter
6892                   )) then
6893           availableInsertionsIndex := availableInsertionsIndex + 1;
6894           availableInsertionsOut(availableInsertionsIndex).item_class := ame_util.headerItemClassName;
6895           availableInsertionsOut(availableInsertionsIndex).item_id := engTransactionId;
6896           availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
6897           availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
6898           availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.firstPostApprover;
6899           availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
6900           availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
6901           availableInsertionsOut(availableInsertionsIndex).authority := ame_util.postApprover;
6902           availableInsertionsOut(availableInsertionsIndex).description := ame_util.firstPostApproverDescription;
6903         end if;
6904       elsif (positionIn = engStApproversCount + 1) then
6905         if (engStApprovers(engStApproversCount).authority <> ame_util.postApprover) then
6906           tempParameter := ame_util.firstPostParameter ||
6907                            ame_util.fieldDelimiter ||
6908                            engStApprovers(engStApproversCount).item_class ||
6909                            ame_util.fieldDelimiter ||
6910                            engStApprovers(engStApproversCount).item_id;
6911           if (not ame_engine.insertionExists
6912                     (orderTypeIn   => ame_util.firstPostApprover
6913                     ,parameterIn   => tempParameter
6914                     )) then
6915             availableInsertionsIndex := availableInsertionsIndex + 1;
6916             availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(engStApproversCount).item_class;
6917             availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(engStApproversCount).item_id;
6918             availableInsertionsOut(availableInsertionsIndex).action_type_id :=
6919                                                                         ame_util.nullInsertionActionTypeId;
6920             availableInsertionsOut(availableInsertionsIndex).group_or_chain_id :=
6921                                                                       ame_util.nullInsertionGroupOrChainId;
6922             availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.firstPostApprover;
6923             availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
6924             availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
6925             availableInsertionsOut(availableInsertionsIndex).authority := ame_util.postApprover;
6926             availableInsertionsOut(availableInsertionsIndex).description := ame_util.firstPostApproverDescription;
6927           end if;
6928         end if;
6929       elsif (positionIn = 1) then
6930         if (engStApprovers(1).authority = ame_util.postApprover) then
6931           tempParameter := ame_util.firstPostParameter ||
6932                            ame_util.fieldDelimiter ||
6933                            engStApprovers(1).item_class ||
6934                            ame_util.fieldDelimiter ||
6935                            engStApprovers(1).item_id;
6936           if (not ame_engine.insertionExists
6937                     (orderTypeIn   => ame_util.firstPostApprover
6938                     ,parameterIn   => tempParameter
6939                     )) then
6940             availableInsertionsIndex := availableInsertionsIndex + 1;
6941             availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(1).item_class;
6942             availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(1).item_id;
6943             availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
6944             availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
6945             availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.firstPostApprover;
6946             availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
6947             availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
6948             availableInsertionsOut(availableInsertionsIndex).authority := ame_util.postApprover;
6949             availableInsertionsOut(availableInsertionsIndex).description := ame_util.firstPostApproverDescription;
6950           end if;
6951         end if;
6952       else
6953         if (engStApprovers(positionIn - 1).item_id = engStApprovers(positionIn).item_id and
6954             engStApprovers(positionIn - 1).item_class = engStApprovers(positionIn).item_class) then
6955           if (engStApprovers(positionIn - 1).authority <> ame_util.postApprover and
6956               engStApprovers(positionIn).authority = ame_util.postApprover) then
6957             tempParameter := ame_util.firstPostParameter ||
6958                              ame_util.fieldDelimiter ||
6959                              engStApprovers(positionIn).item_class ||
6960                              ame_util.fieldDelimiter ||
6961                              engStApprovers(positionIn).item_id;
6962             if (not ame_engine.insertionExists
6963                       (orderTypeIn => ame_util.firstPostApprover
6964                       ,parameterIn => tempParameter
6965                       )) then
6966               availableInsertionsIndex := availableInsertionsIndex + 1;
6967               availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn).item_class;
6968               availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn).item_id;
6969               availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
6970               availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
6971               availableInsertionsOut(availableInsertionsIndex).group_or_chain_id :=
6972                                                             engStApprovers(positionIn).group_or_chain_id;
6973               availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.firstPostApprover;
6974               availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
6975               availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
6976               availableInsertionsOut(availableInsertionsIndex).authority := ame_util.postApprover;
6977               availableInsertionsOut(availableInsertionsIndex).description := ame_util.firstPostApproverDescription;
6978             end if;
6979           end if;
6980         else
6981           if (engStApprovers(positionIn).authority = ame_util.postApprover) then
6982             tempParameter := ame_util.firstPostParameter ||
6983                              ame_util.fieldDelimiter ||
6984                              engStApprovers(positionIn).item_class ||
6985                              ame_util.fieldDelimiter ||
6986                              engStApprovers(positionIn).item_id;
6987             if (not ame_engine.insertionExists
6988                       (orderTypeIn   => ame_util.firstPostApprover
6989                       ,parameterIn   => tempParameter
6990                       )) then
6991               availableInsertionsIndex := availableInsertionsIndex + 1;
6992               availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn).item_class;
6993               availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn).item_id;
6994               availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
6995               availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
6996               availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.firstPostApprover;
6997               availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
6998               availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
6999               availableInsertionsOut(availableInsertionsIndex).authority := ame_util.postApprover;
7000               availableInsertionsOut(availableInsertionsIndex).description := ame_util.firstPostApproverDescription;
7001             end if;
7002           end if;
7003 
7004           if (engStApprovers(positionIn - 1).authority <> ame_util.postApprover) then
7005             tempParameter := ame_util.firstPostParameter ||
7006                              ame_util.fieldDelimiter ||
7007                              engStApprovers(positionIn - 1).item_class ||
7008                              ame_util.fieldDelimiter ||
7009                              engStApprovers(positionIn - 1).item_id;
7010             if (not ame_engine.insertionExists
7011                       (orderTypeIn   => ame_util.firstPostApprover
7012                       ,parameterIn   => tempParameter
7013                       )) then
7014               availableInsertionsIndex := availableInsertionsIndex + 1;
7015               availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn - 1).item_class;
7016               availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn - 1).item_id;
7017               availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7018               availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7019               availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.firstPostApprover;
7020               availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7021               availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7022               availableInsertionsOut(availableInsertionsIndex).authority := ame_util.postApprover;
7023               availableInsertionsOut(availableInsertionsIndex).description := ame_util.firstPostApproverDescription;
7024             end if;
7025           end if;
7026         end if;
7027       end if;
7028     end if;
7029 
7030     /*
7031       ORDER TYPE:  firstPreApprover
7032       Assume that in the case of an entirely empty approver list, we allow insertion of a first
7033       pre-approver into the header item's list only.  Otherwise, we only allow insertion of a
7034       first pre-approver into a non-empty item list.  Here is the case analysis:
7035         if(the approver list is empty) then
7036           allow a first-pre-approver insertion for the header item
7037         elsif(positionIn = 1) then
7038           allow a first-pre-approver insertion for the first approver's item
7039         elsif(positionIn < engStApproversCount + 1) then
7040           if(the engStApprovers at positionIn - 1 and positionIn are for different items) then
7041             allow a first-pre-approver insertion for the second approver's item
7042           end if
7043         end if
7044     */
7045     if (orderTypeIn is null or
7046         orderTypeIn = ame_util.firstPreApprover) then
7047 
7048       if (engStApproversCount = 0) then
7049         tempParameter := ame_util.firstPreApprover ||
7050                          ame_util.fieldDelimiter ||
7051                          ame_util.headerItemClassName ||
7052                          ame_util.fieldDelimiter ||
7053                          engTransactionId;
7054         if (not ame_engine.insertionExists
7055                   (orderTypeIn => ame_util.firstPreApprover
7056                   ,parameterIn => tempParameter
7057                   )) then
7058           availableInsertionsIndex := availableInsertionsIndex + 1;
7059           availableInsertionsOut(availableInsertionsIndex).item_class := ame_util.headerItemClassName;
7060           availableInsertionsOut(availableInsertionsIndex).item_id := engTransactionId;
7061           availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7062           availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7063           availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.firstPreApprover;
7064           availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7065           availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7066           availableInsertionsOut(availableInsertionsIndex).authority := ame_util.preApprover;
7067           availableInsertionsOut(availableInsertionsIndex).description := ame_util.firstPreApproverDescription;
7068         end if;
7069       elsif (positionIn = 1) then
7070         tempParameter := ame_util.firstPreApprover ||
7071                          ame_util.fieldDelimiter ||
7072                          engStApprovers(1).item_class ||
7073                          ame_util.fieldDelimiter ||
7074                          engStApprovers(1).item_id;
7075         if (not ame_engine.insertionExists
7076                   (orderTypeIn   => ame_util.firstPreApprover
7077                   ,parameterIn   => tempParameter
7078                   )) then
7079           availableInsertionsIndex := availableInsertionsIndex + 1;
7080           availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(1).item_class;
7081           availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(1).item_id;
7082           availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7083           availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7084           availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.firstPreApprover;
7085           availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7086           availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7087           availableInsertionsOut(availableInsertionsIndex).authority := ame_util.preApprover;
7088           availableInsertionsOut(availableInsertionsIndex).description := ame_util.firstPreApproverDescription;
7089         end if;
7090       elsif (positionIn < engStApproversCount + 1) then
7091         if (engStApprovers(positionIn - 1).item_id <> engStApprovers(positionIn).item_id or
7092             engStApprovers(positionIn - 1).item_class <> engStApprovers(positionIn).item_class) then
7093           tempParameter := ame_util.firstPreApprover ||
7094                            ame_util.fieldDelimiter ||
7095                            engStApprovers(positionIn).item_class ||
7096                            ame_util.fieldDelimiter ||
7097                            engStApprovers(positionIn).item_id;
7098           if (not ame_engine.insertionExists
7099                     (orderTypeIn   => ame_util.firstPreApprover
7100                     ,parameterIn   => tempParameter
7101                     )) then
7102             availableInsertionsIndex := availableInsertionsIndex + 1;
7103             availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn).item_class;
7104             availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn).item_id;
7105             availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7106             availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7107             availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.firstPreApprover;
7108             availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7109             availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7110             availableInsertionsOut(availableInsertionsIndex).authority := ame_util.preApprover;
7111             availableInsertionsOut(availableInsertionsIndex).description := ame_util.firstPreApproverDescription;
7112           end if;
7113         end if;
7114       end if;
7115     end if;
7116 
7117     /*
7118       ORDER TYPE:  lastPostApprover
7119       Assume that in the case of an entirely empty approver list, we allow insertion of a last
7120       post-approver into the header item's list only.  Otherwise, we only allow insertion of a
7121       last post-approver into a non-empty item list.  Here is the case analysis:
7122         if(the approver list is empty) then
7123           allow last-post-approver insertion for the header item
7124         elsif(positionIn = engStApproversCount + 1) then
7125           allow last-post-approver insertion for the last approver's item
7126         elsif(positionIn > 1) then
7127           if(the engStApprovers at positionIn - 1 and positionIn are for different items) then
7128             allow last-post-approver insertion for the former approver's item
7129           end if
7130         end if
7131     */
7132     if (orderTypeIn is null or
7133         orderTypeIn = ame_util.lastPostApprover) then
7134       if (engStApproversCount = 0) then
7135         tempParameter := ame_util.lastPostApprover ||
7136                          ame_util.fieldDelimiter ||
7137                          ame_util.headerItemClassName ||
7138                          ame_util.fieldDelimiter ||
7139                          engTransactionId;
7140         if (not ame_engine.insertionExists
7141                   (orderTypeIn   => ame_util.lastPostApprover
7142                   ,parameterIn   => tempParameter
7143                   )) then
7144           availableInsertionsIndex := availableInsertionsIndex + 1;
7145           availableInsertionsOut(availableInsertionsIndex).item_class := ame_util.headerItemClassName;
7146           availableInsertionsOut(availableInsertionsIndex).item_id := engTransactionId;
7147           availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7148           availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7149           availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.lastPostApprover;
7150           availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7151           availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7152           availableInsertionsOut(availableInsertionsIndex).authority := ame_util.postApprover;
7153           availableInsertionsOut(availableInsertionsIndex).description := ame_util.lastPostApproverDescription;
7154         end if;
7155       elsif (positionIn = engStApproversCount + 1) then
7156         tempParameter := ame_util.lastPostApprover ||
7157                          ame_util.fieldDelimiter ||
7158                          engStApprovers(engStApproversCount).item_class ||
7159                          ame_util.fieldDelimiter ||
7160                          engStApprovers(engStApproversCount).item_id;
7161         if (not ame_engine.insertionExists
7162                   (orderTypeIn => ame_util.lastPostApprover
7163                   ,parameterIn => tempParameter
7164                   )) then
7165           availableInsertionsIndex := availableInsertionsIndex + 1;
7166           availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(engStApproversCount).item_class;
7167           availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(engStApproversCount).item_id;
7168           availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7169           availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7170           availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.lastPostApprover;
7171           availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7172           availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7173           availableInsertionsOut(availableInsertionsIndex).authority := ame_util.postApprover;
7174           availableInsertionsOut(availableInsertionsIndex).description := ame_util.lastPostApproverDescription;
7175         end if;
7176       elsif (positionIn > 1) then
7177         if (engStApprovers(positionIn - 1).item_id <> engStApprovers(positionIn).item_id or
7178             engStApprovers(positionIn - 1).item_class <> engStApprovers(positionIn).item_class) then
7179           tempParameter := ame_util.lastPostApprover ||
7180                            ame_util.fieldDelimiter ||
7181                            engStApprovers(positionIn - 1).item_class ||
7182                            ame_util.fieldDelimiter ||
7183                            engStApprovers(positionIn - 1).item_id;
7184           if (not ame_engine.insertionExists
7185                     (orderTypeIn   => ame_util.lastPostApprover
7186                     ,parameterIn   => tempParameter
7187                     )) then
7188             availableInsertionsIndex := availableInsertionsIndex + 1;
7189             availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn - 1).item_class;
7190             availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn - 1).item_id;
7191             availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7192             availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7193             availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.lastPostApprover;
7194             availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7195             availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7196             availableInsertionsOut(availableInsertionsIndex).authority := ame_util.postApprover;
7197             availableInsertionsOut(availableInsertionsIndex).description := ame_util.lastPostApproverDescription;
7198           end if;
7199         end if;
7200       end if;
7201     end if;
7202 
7203     /*
7204       ORDER TYPE:  lastPreApprover
7205       Assume that in the case of an entirely empty approver list, we allow insertion of a last
7206       pre-approver into the header item's list only.  Otherwise, we only allow insertion of a
7207       last pre-approver into a non-empty item list.  Here is the case analysis:
7208         if(the approver list is empty) then
7209           allow last-pre-approver insertion for the header item
7210         elsif(positionIn = 1) then
7211           if(the approver at position 1 is not a pre-approver) then
7212             allow last-pre-approver insertion for the item of the first approver
7213           end if
7214         elsif(positionIn <= engStApproversCount) then
7215           if(the engStApprovers at positionIn - 1 and positionIn are for the same item) then
7216             if(the approver at positionIn - 1 is a pre-approver and
7217                the approver at positionIn is not a pre-approver) then
7218               allow last-pre-approver insertion for the engStApprovers' item
7219             end if
7220           else
7221             if(the approver at positionIn is not a pre-approver) then
7222               allow last-pre-approver insertion for the item of the approver at positionIn
7223             end if
7224           end if
7225         end if
7226     */
7227     if (orderTypeIn is null or
7228         orderTypeIn = ame_util.lastPreApprover) then
7229       if (engStApproversCount = 0) then
7230         tempParameter := ame_util.lastPreApprover ||
7231                          ame_util.fieldDelimiter ||
7232                          ame_util.headerItemClassName ||
7233                          ame_util.fieldDelimiter ||
7234                          engTransactionId;
7235         if (not ame_engine.insertionExists
7236                   (orderTypeIn => ame_util.lastPreApprover
7237                   ,parameterIn => tempParameter)) then
7238           availableInsertionsIndex := availableInsertionsIndex + 1;
7239           availableInsertionsOut(availableInsertionsIndex).item_class := ame_util.headerItemClassName;
7240           availableInsertionsOut(availableInsertionsIndex).item_id := engTransactionId;
7241           availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7242           availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7243           availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.lastPreApprover;
7244           availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7245           availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7246           availableInsertionsOut(availableInsertionsIndex).authority := ame_util.preApprover;
7247           availableInsertionsOut(availableInsertionsIndex).description := ame_util.lastPreApproverDescription;
7248         end if;
7249       elsif (positionIn = 1) then
7250         if (engStApprovers(1).authority <> ame_util.preApprover) then
7251           tempParameter := ame_util.lastPreApprover ||
7252                            ame_util.fieldDelimiter ||
7253                            engStApprovers(1).item_class ||
7254                            ame_util.fieldDelimiter ||
7255                            engStApprovers(1).item_id;
7256           if (not ame_engine.insertionExists
7257                     (orderTypeIn   => ame_util.lastPreApprover
7258                     ,parameterIn   => tempParameter
7259                     )) then
7260             availableInsertionsIndex := availableInsertionsIndex + 1;
7261             availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(1).item_class;
7262             availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(1).item_id;
7263             availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7264             availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7265             availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.lastPreApprover;
7266             availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7267             availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7268             availableInsertionsOut(availableInsertionsIndex).authority := ame_util.preApprover;
7269             availableInsertionsOut(availableInsertionsIndex).description := ame_util.lastPreApproverDescription;
7270           end if;
7271         end if;
7272       elsif (positionIn <= engStApproversCount) then
7273         if (engStApprovers(positionIn - 1).item_id = engStApprovers(positionIn).item_id and
7274             engStApprovers(positionIn - 1).item_class = engStApprovers(positionIn).item_class) then
7275           if (engStApprovers(positionIn - 1).authority = ame_util.preApprover and
7276               engStApprovers(positionIn).authority <> ame_util.preApprover) then
7277             tempParameter := ame_util.lastPreApprover ||
7278                              ame_util.fieldDelimiter ||
7279                              engStApprovers(positionIn).item_class ||
7280                              ame_util.fieldDelimiter ||
7281                              engStApprovers(positionIn).item_id;
7282             if (not ame_engine.insertionExists
7283                       (orderTypeIn  => ame_util.lastPreApprover
7284                       ,parameterIn  => tempParameter
7285                       )) then
7286               availableInsertionsIndex := availableInsertionsIndex + 1;
7287               availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn).item_class;
7288               availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn).item_id;
7289               availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7290               availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7291               availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.lastPreApprover;
7292               availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7293               availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7294               availableInsertionsOut(availableInsertionsIndex).authority := ame_util.preApprover;
7295               availableInsertionsOut(availableInsertionsIndex).description := ame_util.lastPreApproverDescription;
7296             end if;
7297           end if;
7298         else
7299           if (engStApprovers(positionIn).authority <> ame_util.preApprover) then
7300             tempParameter := ame_util.lastPreApprover ||
7301                              ame_util.fieldDelimiter ||
7302                              engStApprovers(positionIn).item_class ||
7303                              ame_util.fieldDelimiter ||
7304                              engStApprovers(positionIn).item_id;
7305             if (not ame_engine.insertionExists
7306                       (orderTypeIn   => ame_util.lastPreApprover
7307                       ,parameterIn   => tempParameter
7308                       )) then
7309               availableInsertionsIndex := availableInsertionsIndex + 1;
7310               availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn).item_class;
7311               availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn).item_id;
7312               availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7313               availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7314               availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.lastPreApprover;
7315               availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7316               availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7317               availableInsertionsOut(availableInsertionsIndex).authority := ame_util.preApprover;
7318               availableInsertionsOut(availableInsertionsIndex).description := ame_util.lastPreApproverDescription;
7319             end if;
7320           end if;
7321         end if;
7322       end if;
7323     end if;
7324 
7325   exception
7326     when invalidPositionException then
7327       errorCode := -20001;
7328       errorMessage := ame_util.getMessage
7329         (applicationShortNameIn   =>'PER'
7330         ,messageNameIn            => 'AME_400418_INVALID_INSERTION'
7331         );
7332       ame_util.runtimeException
7333         (packageNameIn     => 'ame_engine'
7334         ,routineNameIn     => 'getInsertions'
7335         ,exceptionNumberIn => errorCode
7336         ,exceptionStringIn => errorMessage
7337         );
7338       raise_application_error(errorCode,errorMessage);
7339 
7340     when others then
7341       ame_util.runtimeException
7342         (packageNameIn     => 'ame_engine'
7343         ,routineNameIn     => 'getInsertions'
7344         ,exceptionNumberIn => sqlcode
7345         ,exceptionStringIn => sqlerrm
7346         );
7347       raise;
7348   end getInsertions;
7349   procedure getLMCondition(ruleIdIn in integer,
7350                            parameterOneOut out nocopy varchar2,
7351                            parameterTwoOut out nocopy varchar2) as
7352     errorCode integer;
7353     errorMessage ame_util.longestStringType;
7354     invalidNameException exception;
7355     tempRuleKey ame_rules.rule_key%type;
7356     parameterOne ame_conditions.parameter_one%type;
7357     parameterTwo ame_conditions.parameter_two%type;
7358     begin
7359       /* Checked for cached values. */
7360       if(not engLMParameterOnes.exists(ruleIdIn)) then
7361         /* Select the values, as they were not cached. */
7362         select
7363           ame_conditions.parameter_one,
7364           ame_conditions.parameter_two
7365           into
7366             parameterOne,
7367             parameterTwo
7368           from
7369             ame_conditions,
7370             ame_condition_usages
7371           where
7372             ame_condition_usages.rule_id = ruleIdIn and
7373             ame_condition_usages.condition_id = ame_conditions.condition_id and
7374             ame_conditions.condition_type = ame_util.listModConditionType and
7375             engEffectiveRuleDate between
7376               ame_conditions.start_date and
7377               nvl(ame_conditions.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
7378             engEffectiveRuleDate between
7379               ame_condition_usages.start_date and
7380               nvl(ame_condition_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
7381             rownum < 2; /* Avoids second fetch otherwise required by ANSI standard to check for too many rows. */
7382         /* Check for an invalid wf_roles.name value in parameter_two. */
7383         if(parameterTwo = ame_util.invalidApproverWfRolesName) then
7384           raise invalidNameException;
7385         end if;
7386         /* Cache the values. */
7387         engLMParameterOnes(ruleIdIn) := parameterOne;
7388         engLMParameterTwos(ruleIdIn) := parameterTwo;
7389       end if;
7390       /* Return the values. */
7391       parameterOneOut := engLMParameterOnes(ruleIdIn);
7392       parameterTwoOut := engLMParameterTwos(ruleIdIn);
7393       exception
7394         when invalidNameException then
7395           tempRuleKey := ame_rule_pkg.getRuleKey(ruleIdIn => ruleIdIn);
7396           errorCode := -20001;
7397           errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
7398                                               messageNameIn => 'AME_400685_INV_LM_RULE',
7399                                               tokenNameOneIn  => 'RULE_KEY',
7400                                               tokenValueOneIn => tempRuleKey);
7401           ame_util.runtimeException(packageNameIn => 'ame_engine',
7402                                     routineNameIn => 'getLMCondition',
7403                                     exceptionNumberIn => errorCode,
7404                                     exceptionStringIn => errorMessage);
7405           raise_application_error(errorCode,
7406                                   errorMessage);
7407         when others then
7408           ame_util.runtimeException(packageNameIn => 'ame_engine',
7409                                     routineNameIn => 'getLMCondition',
7410                                     exceptionNumberIn => sqlcode,
7411                                     exceptionStringIn => sqlerrm);
7412           raise;
7413     end getLMCondition;
7414   procedure getNextApprovers(
7415             applicationIdIn   in number
7416            ,transactionTypeIn in varchar2
7417            ,transactionIdIn   in varchar2
7418            ,nextApproversType in number
7419            ,flagApproversAsNotifiedIn in varchar2 default ame_util.booleanTrue
7420            ,approvalProcessCompleteYNOut out nocopy varchar2
7421            ,nextApproversOut             out nocopy ame_util.approversTable2
7422            ,itemIndexesOut               out nocopy ame_util.idList
7423            ,itemClassesOut               out nocopy ame_util.stringList
7424            ,itemIdsOut                   out nocopy ame_util.stringList
7425            ,itemSourcesOut               out nocopy ame_util.longStringList
7426            ,productionIndexesOut         out nocopy ame_util.idList
7427            ,variableNamesOut             out nocopy ame_util.stringList
7428            ,variableValuesOut            out nocopy ame_util.stringList
7429            ,transVariableNamesOut        out nocopy ame_util.stringList
7430            ,transVariableValuesOut       out nocopy ame_util.stringList) as
7431       allItemsNotSuspended boolean;
7432       ameApplicationId integer;
7433       copyAncillaryData  boolean;
7434       nextApproverCount integer;
7435       nextTreeNodeIndex integer;
7436       tempTreeNodeIndex integer;
7437       approverItemCount integer;
7438       approverProdCount integer;
7439       currentTreeNode ame_util.approverTreeRecord;
7440       evaluateNextNode boolean;
7441       currentOrderNumber integer;
7442       nextApproverTreeIndexList ame_util.idList;
7443       currentApproverIndex integer;
7444       tempApproverIndexes ame_util.idList;
7445 --      tempItemClass ame_util.stringType;
7446 --      tempItemId    ame_util.stringType;
7447       processSibling boolean;
7448       tempTreeNode ame_util.approverTreeRecord;
7449       -- following two variables added - to use incase of item_class is null
7450       tempItemClass ame_util.stringType;
7451       tempItemId    ame_util.stringType;
7452       -- repeated
7453       tempRepeatedCount integer;
7454       tempRepeatedCount2 integer;
7455       tempPrepareItemData boolean := true;
7456       tempProcessProductionActions boolean := false;
7457       tempProcessProductionRules   boolean := false;
7458       tempTreeLevelId integer;
7459       --+
7460       previousNodeOrderNumber integer;
7461       previousTreeLevelId     varchar2(320);
7462       previousNodeStatus      integer;
7463       --+
7464       prevApproverOrderNumber integer;
7465       prevApproverName        varchar2(320);
7466       prevApproverStatus      integer;
7467       --+
7468     begin
7469       if nextApproversType = 4 then
7470         tempPrepareItemData := false;
7471       end if;
7472       if nextApproversType = 2 or nextApproversType = 3 then
7473         tempProcessProductionActions := true;
7474       end if;
7475       if nextApproversType = 3 then
7476         tempProcessProductionRules := true;
7477       end if;
7478       ame_engine.lockTransaction(fndApplicationIdIn => applicationIdIn,
7479                                  transactionIdIn => transactionIdIn,
7480                                  transactionTypeIdIn => transactionTypeIn);
7481       ame_engine.updateTransactionState(isTestTransactionIn  => false
7482                                        ,isLocalTransactionIn => false
7483                                        ,fetchConfigVarsIn    => true
7484                                        ,fetchOldApproversIn  => true
7485                                        ,fetchInsertionsIn    => true
7486                                        ,fetchDeletionsIn     => true
7487                                        ,fetchAttributeValuesIn      => true
7488                                        ,fetchInactiveAttValuesIn    => false
7489                                        ,processProductionActionsIn  => tempProcessProductionActions
7490                                        ,processProductionRulesIn    => tempProcessProductionRules
7491                                        ,updateCurrentApproverListIn => true
7492                                        ,updateOldApproverListIn     => true
7493                                        ,processPrioritiesIn   => true
7494                                        ,prepareItemDataIn     => tempPrepareItemData
7495                                        ,prepareRuleIdsIn      => false
7496                                        ,prepareRuleDescsIn    => false
7497                                        ,prepareApproverTreeIn => true
7498                                        ,transactionIdIn       => transactionIdIn
7499                                        ,ameApplicationIdIn    => null
7500                                        ,fndApplicationIdIn    => applicationIdIn
7501                                        ,transactionTypeIdIn   => transactionTypeIn);
7502       approvalProcessCompleteYNOut := ame_engine.getApprovalProcessCompleteYN;
7503       ameApplicationId := ame_engine.getAmeApplicationId;
7504       /* If approvalProcessCompleteYNOut is 'Y', there should be no nextApprovers. Hence
7505          return with an empty nextApproversOut table */
7506       if approvalProcessCompleteYNOut = ame_util2.completeFullyApproved or
7507          approvalProcessCompleteYNOut = ame_util2.completeFullyRejected or
7508          approvalProcessCompleteYNOut = ame_util2.completePartiallyApproved or
7509          approvalProcessCompleteYNOut = ame_util2.completeNoApprovers then
7510          ame_engine.unlockTransaction(fndApplicationIdIn  => applicationIdIn,
7511                                      transactionIdIn     => transactionIdIn,
7512                                      transactionTypeIdIn => transactionTypeIn);
7513         return;
7514       end if;
7515       copyAncillaryData := false;
7516       nextApproverCount := 0; /* Pre increment */
7517       approverItemCount := 0;
7518       approverProdCount := 0;
7519       nextTreeNodeIndex := 1;
7520       evaluateNextNode := true;
7521       currentOrderNumber := null;
7522       processSibling := true;
7523       loop
7524         currentTreeNode := engStApproversTree(nextTreeNodeIndex);
7525         if currentTreeNode.is_suspended is null or
7526            currentTreeNode.is_suspended = ame_util.booleanFalse then
7527           if currentTreeNode.tree_level = 6 and
7528              (currentTreeNode.status = ame_util.startedStatus
7529                and engStApprovers(currentTreeNode.approver_index).approval_status
7530                     <> ame_util.notifiedByRepeatedStatus)and
7531              (currentTreeNode.sibling_index <> ame_util.noSiblingIndex
7532                and currentTreeNode.min_order <> engStApproversTree(currentTreeNode.sibling_index).min_order ) then
7533             evaluateNextNode := false;
7534           end if;
7535           if evaluateNextNode then
7536             if currentTreeNode.status <> ame_util.completedStatus then
7537               if currentTreeNode.approver_index = ame_util.noApproverIndex and
7538                  evaluateNextNode then
7539                 currentOrderNumber := currentTreeNode.min_order;
7540               end if;
7541             else
7542               currentOrderNumber := null;
7543             end if;
7544             if currentTreeNode.approver_index <> ame_util.noApproverIndex
7545                 and currentOrderNumber is not null
7546                 and currentTreeNode.status = ame_util.notStartedStatus
7547                 and currentTreeNode.min_order = currentOrderNumber
7548                 and (engStApprovers(currentTreeNode.approver_index).approval_status is null
7549                        or engStApprovers(currentTreeNode.approver_index).approval_status
7550                             <> ame_util.notifiedByRepeatedStatus)
7551                   then
7552               nextApproverCount := nextApproverCount + 1;
7553               ame_util.copyApproverRecord2
7554                 (approverRecord2In => engStApprovers(currentTreeNode.approver_index)
7555                 ,approverRecord2Out => nextApproversOut(nextApproverCount));
7556               if flagApproversAsNotifiedIn  = ame_util.booleanTrue then
7557                 setInsertedApprovalStatus(currentApproverIndexIn => currentTreeNode.approver_index
7558                                            ,approvalStatusIn => ame_util.notifiedStatus );
7559               end if;
7560                 currentApproverIndex := currentTreeNode.approver_index;
7561               copyAncillaryData := true;
7562               nextApproverTreeIndexList(nextApproverCount) := nextTreeNodeIndex;
7563               tempApproverIndexes(nextApproverCount) := currentTreeNode.approver_index;
7564               if currentTreeNode.sibling_index <> -1
7565                 and currentTreeNode.max_order <> engStApproversTree(currentTreeNode.sibling_index).max_order then
7566                 processSibling := false;
7567               else
7568                 processSibling := true;
7569               end if;
7570               for x in 1 .. engStRepeatedIndexes.count loop
7571                 if engStRepeatedIndexes(x) = currentTreeNode.approver_index
7572                    and engStRepeatedAppIndexes(x) <> currentTreeNode.approver_index then
7573                       --+
7574                   update ame_temp_old_approver_lists
7575                      set approval_status = ame_util.notifiedByRepeatedStatus
7576                    where application_id = ameApplicationId
7577                      and transaction_id = transactionIdIn
7578                      and name           = engStApprovers(engStRepeatedAppIndexes(x)).name --nextApproversOut(i).name
7579                      and item_class        = engStApprovers(engStRepeatedAppIndexes(x)).item_class
7580                      and item_id           = engStApprovers(engStRepeatedAppIndexes(x)).item_id
7581                      and action_type_id    = engStApprovers(engStRepeatedAppIndexes(x)).action_type_id
7582                      and group_or_chain_id = engStApprovers(engStRepeatedAppIndexes(x)).group_or_chain_id
7583                      and occurrence        = engStApprovers(engStRepeatedAppIndexes(x)).occurrence
7584                      and (approval_status is null or approval_status = ame_util.repeatedStatus);
7585                      engStApprovers(engStRepeatedAppIndexes(x)).approval_status := ame_util.notifiedByRepeatedStatus;
7586                      setInsertedApprovalStatus(currentApproverIndexIn => engStRepeatedAppIndexes(x)
7587                                     ,approvalStatusIn => ame_util.notifiedByRepeatedStatus);
7588                       --+
7589                 end if;
7590               end loop;
7591             end if;
7592             if currentOrderNumber is null and currentTreeNode.tree_level = 6 then
7593               if currentTreeNode.approver_index <> ame_util.noApproverIndex and
7594                  (currentTreeNode.status = ame_util.completedStatus or
7595                   (
7596                     currentTreeNode.status = ame_util.startedStatus
7597                     and engStApprovers(currentTreeNode.approver_index).approval_status <> ame_util.notifiedByRepeatedStatus
7598                     and processSibling
7599                   )or
7600                   (
7601                   currentTreeNode.status = ame_util.notStartedStatus and
7602                   currentTreeNode.sibling_index <> ame_util.noSiblingIndex
7603                   and currentTreeNode.min_order = engStApproversTree(currentTreeNode.sibling_index).min_order
7604                   )
7605                  )and
7606                  processSibling and --evaluateNextNode and
7607                  (currentTreeNode.sibling_index <> ame_util.noSiblingIndex
7608                   and engStApproversTree(currentTreeNode.sibling_index).status = ame_util.notStartedStatus
7609                 and ( engStApprovers(engStApproversTree(currentTreeNode.sibling_index).approver_index).approval_status is null
7610                   or engStApprovers(engStApproversTree(currentTreeNode.sibling_index).approver_index).approval_status
7611                       <> ame_util.notifiedByRepeatedStatus)
7612                   ) then
7613                 --+
7614                 if prevApproverOrderNumber is null or
7615                  (prevApproverOrderNumber < engStApproversTree(currentTreeNode.sibling_index).min_order
7616                  and prevApproverStatus = ame_util.completedStatus) or
7617                  (prevApproverOrderNumber = engStApproversTree(currentTreeNode.sibling_index).min_order )
7618                  then
7619 
7620                 nextApproverCount := nextApproverCount + 1;
7621                 ame_util.copyApproverRecord2
7622                   (approverRecord2In => engStApprovers(engStApproversTree(currentTreeNode.sibling_index).approver_index)
7623                   ,approverRecord2Out => nextApproversOut(nextApproverCount));
7624                 if flagApproversAsNotifiedIn  = ame_util.booleanTrue then
7625                   setInsertedApprovalStatus(currentApproverIndexIn => engStApproversTree(currentTreeNode.sibling_index).approver_index
7626                                            ,approvalStatusIn =>ame_util.notifiedStatus );
7627                 end if;
7628                 nextApproverTreeIndexList(nextApproverCount) := currentTreeNode.sibling_index;
7629                 tempApproverIndexes(nextApproverCount) := engStApproversTree(currentTreeNode.sibling_index).approver_index;
7630                 currentApproverIndex := engStApproversTree(currentTreeNode.sibling_index).approver_index;
7631                 copyAncillaryData := true;
7632                 tempTreeNode := engStApproversTree(currentTreeNode.sibling_index);
7633                 if tempTreeNode.sibling_index <> -1
7634                     and tempTreeNode.max_order <> engStApproversTree(tempTreeNode.sibling_index).max_order then
7635                   processSibling := false;
7636                 else
7637                   processSibling := true;
7638                 end if;
7639                 for x in 1 .. engStRepeatedIndexes.count loop
7640                   if engStRepeatedIndexes(x) = engStApproversTree(currentTreeNode.sibling_index).approver_index
7641                      and engStRepeatedAppIndexes(x) <> engStApproversTree(currentTreeNode.sibling_index).approver_index then
7642                         --+
7643                     update ame_temp_old_approver_lists
7644                        set approval_status = ame_util.notifiedByRepeatedStatus
7645                      where application_id = ameApplicationId
7646                        and transaction_id = transactionIdIn
7647                        and name           = engStApprovers(engStRepeatedAppIndexes(x)).name --nextApproversOut(i).name
7648                        and item_class        = engStApprovers(engStRepeatedAppIndexes(x)).item_class
7649                        and item_id           = engStApprovers(engStRepeatedAppIndexes(x)).item_id
7650                        and action_type_id    = engStApprovers(engStRepeatedAppIndexes(x)).action_type_id
7651                        and group_or_chain_id = engStApprovers(engStRepeatedAppIndexes(x)).group_or_chain_id
7652                        and occurrence        = engStApprovers(engStRepeatedAppIndexes(x)).occurrence
7653                        and (approval_status is null or approval_status = ame_util.repeatedStatus);
7654                        engStApprovers(engStRepeatedAppIndexes(x)).approval_status := ame_util.notifiedByRepeatedStatus;
7655                        setInsertedApprovalStatus(currentApproverIndexIn => engStRepeatedAppIndexes(x)
7656                                                 ,approvalStatusIn => ame_util.notifiedByRepeatedStatus);
7657 
7658                         --+
7659                   end if;
7660                 end loop;
7661               end if;
7662               end if;
7663             end if;
7664           end if;
7665           --+
7666           --prevApproverOrderNumber := currentTreeNode.min_order;
7667           --prevApproverName        := currentTreeNode.tree_level_id;
7668           --prevApproverStatus      := currentTreeNode.status;
7669           --+
7670           if currentTreeNode.tree_level = 6 and (prevApproverOrderNumber is null or
7671              prevApproverOrderNumber = currentTreeNode.min_order)
7672             then
7673             if currentTreeNode.status <> ame_util.completedStatus then
7674               prevApproverStatus := currentTreeNode.status;
7675               prevApproverOrderNumber := currentTreeNode.min_order;
7676               prevApproverName := currentTreeNode.tree_level_id;
7677             end if;
7678           end if;
7679           --+
7680           if currentTreeNode.child_index <> ame_util.noChildIndex and evaluateNextNode then
7681             nextTreeNodeIndex := currentTreeNode.child_index;
7682           else
7683             if evaluateNextNode then
7684               nextTreeNodeIndex := currentTreeNode.sibling_index;
7685               if nextTreeNodeIndex <> ame_util.invalidTreeIndex
7686                  and (currentTreeNode.min_order = engStApproversTree(nextTreeNodeIndex).min_order
7687                  or currentTreeNode.status = ame_util.completedStatus) then
7688                  evaluateNextNode := true;
7689               else
7690                  evaluateNextNode := false;
7691               end if;
7692             else
7693               nextTreeNodeIndex := ame_util.noSiblingIndex;
7694             end if;
7695           end if;
7696         else
7697           nextTreeNodeIndex := currentTreeNode.sibling_index;
7698           prevApproverOrderNumber := null;
7699         end if;
7700         if nextTreeNodeIndex = ame_util.invalidTreeIndex then
7701           /* There are no more siblings or child nodes for the current node */
7702           /* So try moving to the parent's sibling node                     */
7703           /* If the parent's sibling is not found then move to its parent   */
7704           /* and so on ...                                                  */
7705           prevApproverOrderNumber := null;
7706           if currentTreeNode.tree_level = 0 then
7707             tempTreeNodeIndex := ame_util.invalidTreeIndex;
7708           else
7709             tempTreeNodeIndex := currentTreeNode.parent_index;
7710           end if;
7711           if tempTreeNodeIndex <> ame_util.invalidTreeIndex then
7712             processSibling := true;
7713             evaluateNextNode := false;
7714             loop
7715               if engStApproversTree(tempTreeNodeIndex).sibling_index
7716                                                           = ame_util.noSiblingIndex then
7717                 tempTreeNodeIndex := engStApproversTree(tempTreeNodeIndex).parent_index;
7718               else
7719                 nextTreeNodeIndex := engStApproversTree(tempTreeNodeIndex).sibling_index;
7720                 evaluateNextNode := false;
7721                 if (engStApproversTree(tempTreeNodeIndex).min_order
7722                      = engStApproversTree(nextTreeNodeIndex).min_order
7723                    ) or
7724                    (engStApproversTree(tempTreeNodeIndex).status
7725                      = ame_util.completedStatus )
7726                      and
7727                   (previousNodeOrderNumber is null or engStApproversTree(tempTreeNodeIndex).min_order = previousNodeOrderNumber
7728                     and previousNodeStatus = ame_util.completedStatus
7729                   ) then
7730                   evaluateNextNode := true;
7731                 else
7732                   evaluateNextNode := false;
7733                 end if;
7734                 --+
7735                 --previousNodeOrderNumber := engStApproversTree(tempTreeNodeIndex).min_order;
7736                 previousTreeLevelId     := engStApproversTree(tempTreeNodeIndex).tree_level_id;
7737                 --previousNodeStatus      := engStApproversTree(tempTreeNodeIndex).status;
7738                 if previousNodeOrderNumber is null or previousNodeOrderNumber = engStApproversTree(tempTreeNodeIndex).min_order
7739                   then
7740                   if engStApproversTree(tempTreeNodeIndex).status <> ame_util.completedStatus then
7741                     previousNodeStatus := engStApproversTree(tempTreeNodeIndex).status;
7742                     previousNodeOrderNumber := engStApproversTree(tempTreeNodeIndex).min_order;
7743                   end if;
7744                 end if;
7745                 --+
7746                 exit;
7747               end if;
7748               if tempTreeNodeIndex = 1 or tempTreeNodeIndex = ame_util.invalidTreeIndex then
7749                 nextTreeNodeIndex := ame_util.invalidTreeIndex;
7750                 exit;
7751               end if;
7752             end loop;
7753           end if;
7754         end if;
7755         /* When ever we reach this point we come with a valid node which needs     */
7756         /* be processed by the next pass of the loop. If no valid node is present  */
7757         /* this indicates that the entire tree is traversed and there are no more  */
7758         /* approvers to find                                                       */
7759         exit when nextTreeNodeIndex = ame_util.invalidTreeIndex;
7760       end loop;
7761       if copyAncillaryData and nextApproversType < 4 then
7762         ame_engine.prepareItemData(approverIndexesIn  => tempApproverIndexes
7763                                   ,itemIndexesOut     => itemIndexesOut
7764                                   ,itemItemClassesOut => itemClassesOut
7765                                   ,itemIdsOut         => itemIdsOut
7766                                   ,itemSourcesOut     => itemSourcesOut);
7767         if nextApproversType = 2 or nextApproversType = 3 then
7768           preparePerApproverProductions
7769                   (approverIndexesIn   => tempApproverIndexes
7770                   ,itemIndexesIn       => itemIndexesOut
7771                   ,itemSourcesIn       => itemSourcesOut
7772                   ,prodIndexesOut      => productionIndexesOut
7773                   ,productionNamesOut  => variableNamesOut
7774                   ,productionValuesOut => variableValuesOut);
7775         end if;
7776       end if;
7777       if nextApproversType = 3 then
7778         getTransVariableNames(transVariableNamesOut => transVariableNamesOut);
7779         getTransVariableValues(transVariableValuesOut => transVariableValuesOut);
7780       end if;
7781       if flagApproversAsNotifiedIn  = ame_util.booleanTrue then
7782         ameApplicationId := ame_engine.getAmeApplicationId;
7783         for i in 1 .. nextApproversOut.count loop
7784             update ame_temp_old_approver_lists
7785                set approval_status = ame_util.notifiedStatus
7786              where item_class = nextApproversOut(i).item_class
7787                and item_id = nextApproversOut(i).item_id
7788                and name = nextApproversOut(i).name
7789                and action_type_id = nextApproversOut(i).action_type_id
7790                and group_or_chain_id = nextApproversOut(i).group_or_chain_id
7791                and occurrence = nextApproversOut(i).occurrence
7792                and transaction_id = transactionIdIn
7793                and application_id = ameApplicationId;
7794            /* Insert into Approval Notification History Table */
7795           insertIntoTransApprovalHistory
7796             (transactionIdIn         => transactionIdIn
7797             ,applicationIdIn         => ameApplicationId
7798             ,orderNumberIn           => nextApproversOut(i).approver_order_number
7799             ,nameIn                  => nextApproversOut(i).name
7800             ,appCategoryIn           => nextApproversOut(i).approver_category
7801             ,itemClassIn             => nextApproversOut(i).item_class
7802             ,itemIdIn                => nextApproversOut(i).item_id
7803             ,actionTypeIdIn          => nextApproversOut(i).action_type_id
7804             ,authorityIn             => nextApproversOut(i).authority
7805             ,statusIn                => ame_util.notifiedStatus
7806             ,grpOrChainIdIn          => nextApproversOut(i).group_or_chain_id
7807             ,occurrenceIn            => nextApproversOut(i).occurrence
7808             ,apiInsertionIn          => nextApproversOut(i).api_insertion
7809             ,memberOrderNumberIn     => nextApproversOut(i).member_order_number
7810             ,notificationIdIn        => null
7811             ,userCommentsIn          => null
7812             ,dateClearedIn           => null
7813             ,historyTypeIn           => 'APPROVERPRESENT');
7814         end loop;
7815       end if;
7816       if tempPrepareItemData then
7817         for x in 1 .. nextApproversOut.count loop
7818           if engStApprovers(tempApproverIndexes(x)).item_class is null then
7819             nextApproversOut(x).item_class := null;
7820             nextApproversOut(x).item_id    := null;
7821             nextApproversOut(x).source     := null;
7822           end if;
7823         end loop;
7824       end if;
7825       for x in 1 .. nextApproversOut.count loop
7826         if nextApproversOut(x).approval_status = ame_util.repeatedStatus then
7827           nextApproversOut(x).approval_status := null;
7828         end if;
7829       end loop;
7830       ame_engine.unlockTransaction(fndApplicationIdIn  => applicationIdIn,
7831                                    transactionIdIn     => transactionIdIn,
7832                                    transactionTypeIdIn => transactionTypeIn);
7833     exception
7834       when others then
7835         ame_engine.unlockTransaction(fndApplicationIdIn  => applicationIdIn,
7836                                      transactionIdIn     => transactionIdIn,
7837                                      transactionTypeIdIn => transactionTypeIn);
7838         ame_util.runtimeException(packageNameIn => 'ame_engine',
7839                                   routineNameIn => 'getNextApprovers',
7840                                   exceptionNumberIn => sqlcode,
7841                                   exceptionStringIn => sqlerrm);
7842         approvalProcessCompleteYNOut:= null;
7843         nextApproversOut.delete;
7844         raise;
7845   end getNextApprovers;
7846   procedure prepareItemData(approverIndexesIn  in ame_util.idList default ame_util.emptyIdList
7847                            ,itemIndexesOut     out nocopy ame_util.idList
7848                            ,itemItemClassesOut out nocopy ame_util.stringList
7849                            ,itemIdsOut         out nocopy ame_util.stringList
7850                            ,itemSourcesOut     out nocopy ame_util.longStringList) as
7851     tempItemCount integer;
7852     tempItemClass ame_util.stringType;
7853     tempItemId    ame_util.stringType;
7854     tempRuleIdList ame_util.idList;
7855     prevIndex       integer;
7856     currentIndex    integer;
7857     currentApproverIndex integer;
7858     tempIndex       integer;
7859     tempSourceDescription ame_util.longStringType;
7860     tempLength      integer;
7861     tempFlag        boolean;
7862     tempCount       integer;
7863     tempFlag2       boolean;
7864     tempProcessApprover  boolean;
7865     tempProcessApprover2 boolean;
7866     begin
7867       tempItemCount := 0;
7868       prevIndex := null;
7869       tempCount := approverIndexesIn.count;
7870       tempFlag2 := false;
7871       if tempCount = 0 then
7872         tempFlag2  := true;
7873         tempCount := engStApprovers.count;
7874       end if;
7875       /* here tempFlag2 = false indicates the procedure invoked from getNextApprovers*/
7876       for i in 1 .. tempCount loop
7877         if tempFlag2 then
7878           currentApproverIndex := i;
7879         else
7880           currentApproverIndex := approverIndexesIn(i);
7881         end if;
7882         tempProcessApprover := false;
7883         tempProcessApprover2 := false;
7884         if not tempFlag2 then
7885           tempProcessApprover := true;
7886         else
7887           if ( engStApprovers(currentApproverIndex).approval_status is null
7888                 or engStApprovers(currentApproverIndex).approval_status
7889                           not in (ame_util.notifiedByRepeatedStatus
7890                                  ,ame_util.approvedByRepeatedStatus
7891                                  ,ame_util.rejectedByRepeatedStatus
7892                                  ,ame_util.suppressedStatus
7893                                  ,ame_util.repeatedStatus) ) then
7894           tempProcessApprover := true;
7895           end if;
7896         end if;
7897         if tempProcessApprover then
7898           for j in 1 .. engStRepeatedIndexes.count loop
7899             if engStRepeatedIndexes(j) = currentApproverIndex
7900                 and engStRepeatedAppIndexes(j) = currentApproverIndex then
7901               tempItemClass := engStApprovers(currentApproverIndex).item_class;
7902               tempItemId    := engStApprovers(currentApproverIndex).item_id;
7903             end if;
7904           end loop;
7905           for j in 1 .. engStRepeatedIndexes.count loop
7906             if engStRepeatedIndexes(j) = currentApproverIndex
7907                 and engStRepeatedAppIndexes(j) <> currentApproverIndex then
7908               if tempItemClass <> engStApprovers(engStRepeatedAppIndexes(j)).item_class
7909                   or tempItemId <> engStApprovers(engStRepeatedAppIndexes(j)).item_id then
7910                 tempProcessApprover2 := true;
7911               end if;
7912             end if;
7913           end loop;
7914         end if;
7915         if tempProcessApprover2 then
7916           prevIndex := null;
7917           for j in 1 .. engStRepeatedIndexes.count loop
7918             if engStRepeatedIndexes(j) = currentApproverIndex then
7919               currentIndex := engStRepeatedAppIndexes(j);
7920             if (currentApproverIndex = currentIndex)
7921                 or
7922                (engStApprovers(currentIndex).item_id <> tempItemId
7923                  or engStApprovers(currentIndex).item_class <> tempItemClass) then
7924               tempItemCount := tempItemCount + 1;
7925               itemIndexesOut(tempItemCount) := i;
7926               tempFlag := true;
7927               itemItemClassesOut(tempItemCount) := engStApprovers(currentIndex).item_class;
7928               itemIdsOut(tempItemCount) := engStApprovers(currentIndex).item_id;
7929               prevIndex := tempItemCount;
7930             end if;
7931             tempSourceDescription := null;
7932             tempRuleIdList.delete;
7933             ame_util.parseSourceValue(sourceValueIn => engStApprovers(currentIndex).source
7934                                      ,sourceDescriptionOut => tempSourceDescription
7935                                      ,ruleIdListOut => tempRuleIdList);
7936             for z in 1 .. tempRuleIdList.count loop
7937               if itemSourcesOut.count >= tempItemCount then
7938                 tempIndex := instrb(itemSourcesOut(tempItemCount),tempRuleIdList(z));
7939               else
7940                 itemSourcesOut(tempItemCount) := null;
7941                 tempIndex := -1;
7942               end if;
7943               if tempIndex = -1 then
7944                 ame_util.appendRuleIdToSource(ruleIdIn => tempRuleIdList(z)
7945                                              ,sourceInOut => itemSourcesOut(tempItemCount));
7946               end if;
7947             end loop;
7948             end if;
7949           end loop;
7950         end if;
7951         if tempFlag and (not engIsLocalTransaction)then
7952           tempFlag := false;
7953           engStApprovers(currentApproverIndex).item_class := null;
7954           engStApprovers(currentApproverIndex).item_id    := null;
7955           engStApprovers(currentApproverIndex).source     := null;
7956         end if;
7957       end loop;
7958     exception
7959       when others then
7960         ame_util.runtimeException(packageNameIn => 'ame_engine',
7961                                   routineNameIn => 'prepareItemData',
7962                                   exceptionNumberIn => sqlcode,
7963                                   exceptionStringIn => sqlerrm);
7964         itemIndexesOut.delete;
7965         itemItemClassesOut.delete;
7966         itemIdsOut.delete;
7967         itemSourcesOut.delete;
7968         raise;
7969   end prepareItemData;
7970   procedure preparePerApproverProductions
7971            (approverIndexesIn    in ame_util.idList default ame_util.emptyIdList
7972            ,itemIndexesIn        in ame_util.idList default ame_util.emptyIdList
7973            ,itemSourcesIn        in ame_util.longStringList default ame_util.emptyLongStringList
7974            ,prodIndexesOut      out nocopy ame_util.idList
7975            ,productionNamesOut  out nocopy ame_util.stringList
7976            ,productionValuesOut out nocopy ame_util.stringList) as
7977     tempRuleIdList ame_util.idList;
7978     tempSourceDescription ame_util.stringType;
7979     hasRepeatedOccurrences boolean;
7980     currentRepeatedFirstIndex integer;
7981     currentIndex integer;
7982     tempCount integer;
7983     tempPerAppProdIndex integer;
7984     tempProdIndex  integer;
7985     tempFlag2 boolean;
7986     tempCount2 integer;
7987     currentApproverIndex integer;
7988     begin
7989       if not engProcessProductionActions then
7990         return;
7991       end if;
7992       tempProdIndex  := 0;
7993       tempPerAppProdIndex := 0;
7994       tempCount := 1;
7995       tempCount2 := approverIndexesIn.count;
7996       tempFlag2 := false;
7997       if tempCount2 = 0 then
7998         tempFlag2  := true;
7999         tempCount2 := engStApprovers.count;
8000       end if;
8001       /* here tempFlag2 = false indicates the procedure invoked from getNextApprovers */
8002       for i in 1 .. tempCount2 loop
8003         hasRepeatedOccurrences := false;
8004         currentRepeatedFirstIndex := -1;
8005         tempRuleIdList.delete;
8006         tempSourceDescription := null;
8007         tempCount := 1;
8008         if tempFlag2 then
8009           currentApproverIndex := i;
8010         else
8011           currentApproverIndex := approverIndexesIn(i);
8012         end if;
8013         if tempFlag2 then
8014           if engStApprovers(currentApproverIndex).item_class is null then
8015             tempCount := 0;
8016             for x in 1 .. engStItemIndexes.count loop
8017               if engStItemIndexes(x) = currentApproverIndex then
8018                 tempCount := tempCount + 1;
8019                 if currentRepeatedFirstIndex = -1 then
8020                   currentRepeatedFirstIndex := x;
8021                 end if;
8022               end if;
8023             end loop;
8024             hasRepeatedOccurrences := true;
8025           end if;
8026         else
8027           tempCount := 0;
8028           for x in 1 .. itemIndexesIn.count loop
8029             if itemIndexesIn(x) = i then
8030                 tempCount := tempCount + 1;
8031                 if currentRepeatedFirstIndex = -1 then
8032                   currentRepeatedFirstIndex := x;
8033                 end if;
8034             end if;
8035           end loop;
8036           if currentRepeatedFirstIndex <> -1 then
8037             hasRepeatedOccurrences := true;
8038           else
8039             hasRepeatedOccurrences := false;
8040             tempCount := 1;
8041           end if;
8042         end if;
8043         currentIndex := 0;
8044         for j in 1 .. tempCount loop
8045           if hasRepeatedOccurrences then
8046             currentIndex := (currentRepeatedFirstIndex+j)-1;
8047           else
8048             currentIndex := currentApproverIndex;
8049           end if;
8050           tempSourceDescription := null;
8051           tempRuleIdList.delete;
8052           if hasRepeatedOccurrences then
8053             if tempFlag2 then
8054               ame_util.parseSourceValue(sourceValueIn => engStItemSources(currentIndex),
8055                                         sourceDescriptionOut => tempSourceDescription,
8056                                         ruleIdListOut => tempRuleIdList);
8057             else
8058               ame_util.parseSourceValue(sourceValueIn => itemSourcesIn(currentIndex),
8059                                         sourceDescriptionOut => tempSourceDescription,
8060                                         ruleIdListOut => tempRuleIdList);
8061             end if;
8062           else
8063             ame_util.parseSourceValue(sourceValueIn => engStApprovers(currentIndex).source,
8064                                       sourceDescriptionOut => tempSourceDescription,
8065                                       ruleIdListOut => tempRuleIdList);
8066           end if;
8067             for k in 1 .. tempRuleIdList.count loop
8068               if(engAppPerAppProdFirstIndexes.exists(tempRuleIdList(k))) then
8069                 tempPerAppProdIndex := engAppPerAppProdFirstIndexes(tempRuleIdList(k));
8070                 loop
8071                   tempProdIndex := tempProdIndex + 1;
8072                   prodIndexesOut(tempProdIndex) := i;
8073                   productionNamesOut(tempProdIndex) := engAppPerAppProdVariableNames(tempPerAppProdIndex);
8074                   productionValuesOut(tempProdIndex) := engAppPerAppProdVariableValues(tempPerAppProdIndex);
8075                   tempPerAppProdIndex := tempPerAppProdIndex + 1;
8076                   if(not engAppPerAppProdRuleIds.exists(tempPerAppProdIndex) or
8077                    engAppPerAppProdRuleIds(tempPerAppProdIndex) <> tempRuleIdList(k)) then
8078                     exit;
8079                   end if;
8080                 end loop;
8081               end if;
8082             end loop;
8083         end loop;
8084       end loop;
8085     exception
8086       when others then
8087         ame_util.runtimeException(packageNameIn => 'ame_engine',
8088                                   routineNameIn => 'preparePerApproverProductions',
8089                                   exceptionNumberIn => sqlcode,
8090                                   exceptionStringIn => sqlerrm);
8091         prodIndexesOut.delete;
8092         productionNamesOut.delete;
8093         productionValuesOut.delete;
8094         raise;
8095   end preparePerApproverProductions;
8096   procedure prepareRuleData as
8097     tempRuleIdList ame_util.idList;
8098     tempEngStRuleIndex integer;
8099     tempSourceDescription ame_util.stringType;
8100     hasRepeatedOccurrences boolean;
8101     currentRepeatedFirstIndex integer;
8102     currentIndex integer;
8103     tempCount integer;
8104     tempEngStProdIndex  integer;
8105     begin
8106       if not (engPrepareRuleIds
8107                or engPrepareRuleDescs ) then
8108         return;
8109       end if;
8110       tempEngStRuleIndex  := 0;
8111       tempCount := 1;
8112       for i in 1 .. engStApprovers.count loop
8113         hasRepeatedOccurrences := false;
8114         currentRepeatedFirstIndex := -1;
8115         tempRuleIdList.delete;
8116         tempSourceDescription := null;
8117         tempCount := 1;
8118         if engStApprovers(i).item_class is null then
8119           tempCount := 0;
8120           for x in 1 .. engStItemIndexes.count loop
8121             if engStItemIndexes(x) = i then
8122               tempCount := tempCount + 1;
8123               if currentRepeatedFirstIndex = -1 then
8124                 currentRepeatedFirstIndex := x;
8125               end if;
8126             end if;
8127           end loop;
8128           hasRepeatedOccurrences := true;
8129         end if;
8130         currentIndex := 0;
8131         for j in 1 .. tempCount loop
8132           if hasRepeatedOccurrences then
8133             currentIndex := (currentRepeatedFirstIndex+j)-1;
8134           else
8135             currentIndex := i;
8136           end if;
8137           tempSourceDescription := null;
8138           tempRuleIdList.delete;
8139           if hasRepeatedOccurrences then
8140             ame_util.parseSourceValue(sourceValueIn => engStItemSources(currentIndex),
8141                                       sourceDescriptionOut => tempSourceDescription,
8142                                       ruleIdListOut => tempRuleIdList);
8143           else
8144             ame_util.parseSourceValue(sourceValueIn => engStApprovers(currentIndex).source,
8145                                       sourceDescriptionOut => tempSourceDescription,
8146                                       ruleIdListOut => tempRuleIdList);
8147           end if;
8148           if(tempRuleIdList.count = 0) then
8149             tempEngStRuleIndex := tempEngStRuleIndex + 1;
8150             engStRuleIndexes(tempEngStRuleIndex) := i;
8151             engStSourceTypes(tempEngStRuleIndex) := tempSourceDescription;
8152             if(engPrepareRuleIds) then
8153               engStRuleIds(tempEngStRuleIndex) := null;
8154             end if;
8155             if(engPrepareRuleDescs) then
8156               engStRuleDescriptions(tempEngStRuleIndex) := null;
8157             end if;
8158           else
8159             for k in 1 .. tempRuleIdList.count loop
8160               tempEngStRuleIndex := tempEngStRuleIndex + 1;
8161               engStRuleIndexes(tempEngStRuleIndex) := i;
8162               engStSourceTypes(tempEngStRuleIndex) := tempSourceDescription;
8163               if(engPrepareRuleIds) then
8164                 engStRuleIds(tempEngStRuleIndex) := tempRuleIdList(k);
8165               end if;
8166               if(engPrepareRuleDescs) then
8167                 engStRuleDescriptions(tempEngStRuleIndex) :=
8168                   ame_rule_pkg.getDescription(ruleIdIn => tempRuleIdList(k),
8169                                               processingDateIn => engEffectiveRuleDate);
8170               end if;
8171             end loop;
8172           end if;
8173         end loop;
8174       end loop;
8175     exception
8176       when others then
8177         ame_util.runtimeException(packageNameIn => 'ame_engine',
8178                                   routineNameIn => 'prepareRuleData',
8179                                   exceptionNumberIn => sqlcode,
8180                                   exceptionStringIn => sqlerrm);
8181         engStRuleDescriptions.delete;
8182         engStRuleIds.delete;
8183         engStRuleIndexes.delete;
8184         raise;
8185   end prepareRuleData;
8186   procedure getProductionIndexes(productionIndexesOut out nocopy ame_util.idList) as
8187     begin
8188       for i in 1 .. engStProductionIndexes.count loop
8189         productionIndexesOut(i) := engStProductionIndexes(i);
8190       end loop;
8191       exception
8192         when others then
8193           ame_util.runtimeException(packageNameIn => 'ame_engine',
8194                                     routineNameIn => 'getProductionIndexes',
8195                                     exceptionNumberIn => sqlcode,
8196                                     exceptionStringIn => sqlerrm);
8197           raise;
8198     end getProductionIndexes;
8199   procedure getRepeatedIndexes(repeatedIndexesOut out nocopy ame_util.idList
8200                               ,repeatedAppIndexesOut out nocopy ame_util.idList) as
8201     begin
8202       for i in 1 .. engStRepeatedIndexes.count loop
8203         repeatedIndexesOut(i) := engStRepeatedIndexes(i);
8204       end loop;
8205       for i in 1 .. engStRepeatedAppIndexes.count loop
8206         repeatedAppIndexesOut(i) := engStRepeatedAppIndexes(i);
8207       end loop;
8208       exception
8209         when others then
8210           ame_util.runtimeException(packageNameIn => 'ame_engine',
8211                                     routineNameIn => 'getRepeatedIndexes',
8212                                     exceptionNumberIn => sqlcode,
8213                                     exceptionStringIn => sqlerrm);
8214           raise;
8215     end getRepeatedIndexes;
8216   procedure getRuleDescriptions(ruleDescriptionsOut out nocopy ame_util.stringList) as
8217     begin
8218       for i in 1 .. engStRuleDescriptions.count loop
8219         ruleDescriptionsOut(i) := engStRuleDescriptions(i);
8220       end loop;
8221       exception
8222         when others then
8223           ame_util.runtimeException(packageNameIn => 'ame_engine',
8224                                     routineNameIn => 'getRuleDescriptions',
8225                                     exceptionNumberIn => sqlcode,
8226                                     exceptionStringIn => sqlerrm);
8227           raise;
8228     end getRuleDescriptions;
8229   procedure getRuleIds(ruleIdsOut out nocopy ame_util.idList) as
8230     begin
8231       for i in 1 .. engStRuleIds.count loop
8232         ruleIdsOut(i) := engStRuleIds(i);
8233       end loop;
8234       exception
8235         when others then
8236           ame_util.runtimeException(packageNameIn => 'ame_engine',
8237                                     routineNameIn => 'getRuleIds',
8238                                     exceptionNumberIn => sqlcode,
8239                                     exceptionStringIn => sqlerrm);
8240           raise;
8241     end getRuleIds;
8242   procedure getRuleIndexes(ruleIndexesOut out nocopy ame_util.idList) as
8243     begin
8244       for i in 1 .. engStRuleIndexes.count loop
8245         ruleIndexesOut(i) := engStRuleIndexes(i);
8246       end loop;
8247       exception
8248         when others then
8249           ame_util.runtimeException(packageNameIn => 'ame_engine',
8250                                     routineNameIn => 'getRuleIndexes',
8251                                     exceptionNumberIn => sqlcode,
8252                                     exceptionStringIn => sqlerrm);
8253           raise;
8254     end getRuleIndexes;
8255   procedure getRuntimeGroupMembers(groupIdIn in integer,
8256                                    approverNamesOut out nocopy ame_util.longStringList,
8257                                    approverOrderNumbersOut out nocopy ame_util.idList,
8258                                    approverDisplayNamesOut out nocopy ame_util.longStringList,
8259                                    origSystemIdsOut out nocopy ame_util.idList,
8260                                    origSystemsOut out nocopy ame_util.stringList) as
8261     firstNewIndex integer;
8262     tempIndex integer;
8263     begin
8264       tempIndex := 0; /* pre-increment */
8265       -- Check if group is defined or has to be re run for every item class/item ID
8266       if(not engGroupUseItemBind.exists(groupIdIn)) then
8267         fetchRuntimeGroup(groupIdIn => groupIdIn);
8268       elsif (engGroupUseItemBind(groupIdIn) = ame_util.booleanTrue) then
8269         fetchRuntimeGroup(groupIdIn => groupIdIn);
8270       end if;
8271       for i in 1 .. engGroupMemberGroupIds.count loop
8272         if(engGroupMemberGroupIds(i) = groupIdIn) then
8273           tempIndex := tempIndex + 1;
8274           approverNamesOut(tempIndex) := engGroupMemberNames(i);
8275           approverOrderNumbersOut(tempIndex) := engGroupMemberOrderNumbers(i);
8276           approverDisplayNamesOut(tempIndex) := engGroupMemberDisplayNames(i);
8277           origSystemsOut(tempIndex) := engGroupMemberOrigSystems(i);
8278           origSystemIdsOut(tempIndex) := engGroupMemberOrigSystemIds(i);
8279         elsif(tempIndex > 0) then /* We found and have passed the group. */
8280           exit;
8281         end if;
8282       end loop;
8283       /*
8284         If the group is the last one in the engGroup package variables, the above loop
8285         will never arrive at its exit statement, so we need to check for a found group
8286         outside the loop.
8287       */
8288       if(tempIndex > 0) then
8289         return;
8290       end if;
8291       exception
8292         when others then
8293           ame_util.runtimeException(packageNameIn => 'ame_engine',
8294                                     routineNameIn => 'getRuntimeGroupMembers',
8295                                     exceptionNumberIn => sqlcode,
8296                                     exceptionStringIn => sqlerrm);
8297           raise;
8298     end getRuntimeGroupMembers;
8299   procedure getSourceTypes(sourceTypesOut out nocopy ame_util.stringList) as
8300     begin
8301       for i in 1 .. engStSourceTypes.count loop
8302         sourceTypesOut(i) := engStSourceTypes(i);
8303       end loop;
8304       exception
8305         when others then
8306           ame_util.runtimeException(packageNameIn => 'ame_engine',
8307                                     routineNameIn => 'getSourceTypes',
8308                                     exceptionNumberIn => sqlcode,
8309                                     exceptionStringIn => sqlerrm);
8310           raise;
8311     end getSourceTypes;
8312   procedure getTestTransApplicableRules(ruleItemClassIdsOut out nocopy ame_util.idList,
8313                                         itemClassIdsOut out nocopy ame_util.idList,
8314                                         itemIdsOut out nocopy ame_util.stringList,
8315                                         ruleIdsOut out nocopy ame_util.idList,
8316                                         ruleTypesOut out nocopy ame_util.idList,
8317                                         ruleDescriptionsOut out nocopy ame_util.stringList) as
8318     headerItemClassId integer;
8319     switchRows boolean;
8320     tempIndex integer;
8321     tempItemClassId integer;
8322     tempItemId ame_util.stringType;
8323     tempRuleDescription ame_util.stringType;
8324     tempRuleId integer;
8325     tempRuleItemClassId integer;
8326     tempRuleNotFound boolean;
8327     tempRuleType integer;
8328     begin
8329       headerItemClassId := ame_admin_pkg.getItemClassIdByName(itemClassNameIn => ame_util.headerItemClassName);
8330       /* First populate the output lists, eliminating duplicate rules. */
8331       tempIndex := 0; /* pre-increment */
8332       for i in 1 .. engAppRuleIds.count loop
8333         tempRuleNotFound := true;
8334         for j in 1 .. (i - 1) loop
8335           if(engAppRuleIds(j) = engAppRuleIds(i) and
8336              engAppItemClassIds(i) = engAppItemClassIds(j) and
8337              engAppItemIds(i) = engAppItemIds(j)) then
8338             tempRuleNotFound := false;
8339             exit;
8340           end if;
8341         end loop;
8342         if(tempRuleNotFound) then
8343           tempIndex := tempIndex + 1;
8344           ruleIdsOut(tempIndex) := engAppRuleIds(i);
8345           itemClassIdsOut(tempIndex) := engAppItemClassIds(i);
8346           itemIdsOut(tempIndex) := engAppItemIds(i);
8347           ruleTypesOut(tempIndex) := ame_rule_pkg.getRuleType(ruleIdIn => engAppRuleIds(i),
8348                                                               processingDateIn => engEffectiveRuleDate);
8349           ruleItemClassIdsOut(tempIndex) := ame_rule_pkg.getItemClassId(ruleIdIn => engAppRuleIds(i),
8350                                                                         processingDateIn => engEffectiveRuleDate);
8351           ruleDescriptionsOut(tempIndex) := ame_rule_pkg.getDescription(ruleIdIn => engAppRuleIds(i),
8352                                                                         processingDateIn => engEffectiveRuleDate);
8353         end if;
8354       end loop;
8355       /*
8356         Now sort the output lists.  The header-level rules come first, then all other rules.  Among
8357         the header-level rules, sort first by ruleTypesOut, then by itemClassIdsOut, then by itemIdsOut.
8358         (The sort by item class and item ID is only relevant under per-item evaluation, but it's harmless
8359         otherwise, and efficiency is not a concern here.)  Among the non-header-level rules, sort first
8360         by ruleItemClassIdsOut, then by itemClassIdsOut, then by itemIdsOut, then by ruleTypesOut.
8361       */
8362       for i in 2 .. ruleItemClassIdsOut.count loop
8363         for j in 1 .. (i - 1) loop
8364           if(ruleItemClassIdsOut(j) = headerItemClassId and
8365              ruleItemClassIdsOut(i) = headerItemClassId) then
8366             if(ruleTypesOut(i) > ruleTypesOut(j)) then
8367               switchRows := false;
8368             elsif(ruleTypesOut(i) < ruleTypesOut(j)) then
8369               switchRows := true;
8370             else /* ruleTypesOut(i) = ruleTypesOut(j) */
8371               if(itemClassIdsOut(i) > itemClassIdsOut(j)) then
8372                 switchRows := false;
8373               elsif(itemClassIdsOut(i) < itemClassIdsOut(j)) then
8374                 switchRows := true;
8375               else /* itemClassIdsOut(i) = itemClassIdsOut(j) */
8376                 if(itemIdsOut(i) > itemIdsOut(j)) then
8377                   switchRows := false;
8378                 elsif(itemIdsOut(i) < itemIdsOut(j)) then
8379                   switchRows := true;
8380                 else /* itemIdsOut(i) = itemIdsOut(j) */
8381                   switchRows := false;
8382                 end if;
8383               end if;
8384             end if;
8385           elsif(ruleItemClassIdsOut(j) = headerItemClassId and
8386                 (ruleItemClassIdsOut(i) is null or
8387                  ruleItemClassIdsOut(i) <> headerItemClassId)) then
8388             switchRows := false;
8389           elsif((ruleItemClassIdsOut(j) is null or
8390                  ruleItemClassIdsOut(j) <> headerItemClassId) and
8391                 ruleItemClassIdsOut(i) = headerItemClassId) then
8392             switchRows := true;
8393           else /* ruleItemClassIdsOut(j) <> headerItemClassId and ruleItemClassIdsOut(i) <> headerItemClassId */
8394             if(ruleItemClassIdsOut(i) > ruleItemClassIdsOut(j) or
8395                (ruleItemClassIdsOut(i) is null and ruleItemClassIdsOut(j) is not null)) then
8396               switchRows := false;
8397             elsif(ruleItemClassIdsOut(i) < ruleItemClassIdsOut(j) or
8398                   (ruleItemClassIdsOut(i) is not null and ruleItemClassIdsOut(j) is null)) then
8399               switchRows := true;
8400             else /* ruleItemClassIdsOut(i) = ruleItemClassIdsOut(j) or both are null */
8401               if(itemClassIdsOut(i) > itemClassIdsOut(j)) then
8402                 switchRows := false;
8403               elsif(itemClassIdsOut(i) < itemClassIdsOut(j)) then
8404                 switchRows := true;
8405               else /* itemClassIdsOut(i) = itemClassIdsOut(j) */
8406                 if(itemIdsOut(i) > itemIdsOut(j)) then
8407                   switchRows := false;
8408                 elsif(itemIdsOut(i) < itemIdsOut(j)) then
8409                   switchRows := true;
8410                 else /* itemIdsOut(i) = itemIdsOut(j) */
8411                   switchRows := false;
8412                 end if;
8413               end if;
8414             end if;
8415           end if;
8416           if(switchRows) then
8417             /* Assign i values to temp buffers. */
8418             tempRuleItemClassId := ruleItemClassIdsOut(i);
8419             tempItemClassId := itemClassIdsOut(i);
8420             tempItemId := itemIdsOut(i);
8421             tempRuleId := ruleIdsOut(i);
8422             tempRuleType := ruleTypesOut(i);
8423             tempRuleDescription := ruleDescriptionsOut(i);
8424             /* Assign j values to i values. */
8425             ruleItemClassIdsOut(i) := ruleItemClassIdsOut(j);
8426             itemClassIdsOut(i) := itemClassIdsOut(j);
8427             itemIdsOut(i) := itemIdsOut(j);
8428             ruleIdsOut(i) := ruleIdsOut(j);
8429             ruleTypesOut(i) := ruleTypesOut(j);
8430             ruleDescriptionsOut(i) := ruleDescriptionsOut(j);
8431             /* Assign temp buffers to j values. */
8432             ruleItemClassIdsOut(j) := tempRuleItemClassId;
8433             itemClassIdsOut(j) := tempItemClassId;
8434             itemIdsOut(j) := tempItemId;
8435             ruleIdsOut(j) := tempRuleId;
8436             ruleTypesOut(j) := tempRuleType;
8437             ruleDescriptionsOut(j) := tempRuleDescription;
8438           end if;
8439         end loop;
8440       end loop;
8441       exception
8442         when others then
8443           ame_util.runtimeException(packageNameIn => 'ame_engine',
8444                                     routineNameIn => 'getTestTransApplicableRules',
8445                                     exceptionNumberIn => sqlcode,
8446                                     exceptionStringIn => sqlerrm);
8447           raise;
8448     end getTestTransApplicableRules;
8449   procedure getTestTransApprovers(isTestTransactionIn in boolean,
8450                                   transactionIdIn in varchar2,
8451                                   ameApplicationIdIn in integer,
8452                                   approverListStageIn in integer,
8453                                   approversOut out nocopy ame_util.approversTable2,
8454                                   productionIndexesOut out nocopy ame_util.idList,
8455                                   variableNamesOut out nocopy ame_util.stringList,
8456                                   variableValuesOut out nocopy ame_util.stringList) as
8457     tempCount integer;
8458     begin
8459       if(not isTestTransactionIn) then
8460         /*
8461           Make sure a real transaction gets logged and its state initialized.  (This is usually
8462           only necessary for "real" transactions created for debugging purposes.)
8463         */
8464         select count(*)
8465           into tempCount
8466           from ame_temp_transactions
8467           where
8468             application_id = ameApplicationIdIn and
8469             transaction_id = transactionIdIn and
8470             rownum < 2; /* Avoids second fetch otherwise required by ANSI standard to check for too many rows. */
8471         if(tempCount = 0) then
8472           insert into ame_temp_transactions(
8473             application_id,
8474             transaction_id,
8475             row_timestamp) values(
8476               ameApplicationIdIn,
8477               transactionIdIn,
8478               sysdate); /* Don't use engEffectiveRuleDate here. */
8479           updateTransactionState(isTestTransactionIn => false,
8480                                  isLocalTransactionIn => true,
8481                                  fetchConfigVarsIn => true,
8482                                  fetchOldApproversIn => true,
8483                                  fetchInsertionsIn => true,
8484                                  fetchDeletionsIn => true,
8485                                  fetchAttributeValuesIn => true,
8486                                  fetchInactiveAttValuesIn => false,
8487                                  processProductionActionsIn => false,
8488                                  processProductionRulesIn => false,
8489                                  updateCurrentApproverListIn => true,
8490                                  updateOldApproverListIn => true,
8491                                  processPrioritiesIn => true,
8492                                  prepareItemDataIn => true,
8493                                  prepareRuleIdsIn => true,
8494                                  prepareRuleDescsIn => false,
8495                                  prepareApproverTreeIn => true,
8496                                  transactionIdIn => transactionIdIn,
8497                                  ameApplicationIdIn => ameApplicationIdIn);
8498         end if;
8499       end if;
8500       setContext(isTestTransactionIn => isTestTransactionIn,
8501                  isLocalTransactionIn => true,
8502                  fetchConfigVarsIn => true,
8503                  fetchOldApproversIn => true,
8504                  fetchInsertionsIn => approverListStageIn > 1,
8505                  fetchDeletionsIn => approverListStageIn > 2,
8506                  fetchAttributeValuesIn => true,
8507                  fetchInactiveAttValuesIn => false,
8508                  processProductionActionsIn => true,
8509                  processProductionRulesIn => true,
8510                  updateCurrentApproverListIn => true,
8511                  updateOldApproverListIn => true,
8512                  processPrioritiesIn => true,
8513                  prepareItemDataIn => true,
8514                  prepareRuleIdsIn => true,
8515                  prepareRuleDescsIn => false,
8516                  prepareApproverTreeIn => true,
8517                  transactionIdIn => transactionIdIn,
8518                  ameApplicationIdIn => ameApplicationIdIn);
8519       evaluateRules;
8520       fetchApplicableActions;
8521       processExceptions;
8522       processRules;
8523       if(approverListStageIn > 1 and not isTestTransactionIn) then
8524         processAdHocInsertions;
8525         processUnresponsiveApprovers;
8526       end if;
8527       if(approverListStageIn > 2 and not isTestTransactionIn) then
8528         if engRepeatSubstitutions  then
8529           repeatSubstitutions;
8530         end if;
8531       end if;
8532       if(approverListStageIn > 3 and not isTestTransactionIn) then
8533         processSuppressions;
8534       end if;
8535       if(approverListStageIn > 4) then
8536         processRepeatedApprovers;
8537       end if;
8538       if(approverListStageIn > 5) then
8539         calculateApproverOrderNumbers;
8540       end if;
8541       populateEngStVariables;
8542       getApprovers(approversOut => approversOut);
8543       getProductionIndexes(productionIndexesOut => productionIndexesOut);
8544       getVariableNames(variableNamesOut=> variableNamesOut);
8545       getVariableValues(variableValuesOut => variableValuesOut);
8546       exception
8547         when others then
8548           rollback;
8549           ame_util.runtimeException(packageNameIn => 'ame_engine',
8550                                     routineNameIn => 'getTestTransApprovers',
8551                                     exceptionNumberIn => sqlcode,
8552                                     exceptionStringIn => sqlerrm);
8553           raise;
8554     end getTestTransApprovers;
8555   procedure getTransVariableNames(transVariableNamesOut out nocopy ame_util.stringList) as
8556     tempIndex integer;
8557     begin
8558       tempIndex := 1;
8559       for i in 1 .. engStProductionsTable.count loop
8560         if engStProductionsTable(i).item_class = ame_util.headerItemClassName and
8561          engStProductionsTable(i).item_id = engTransactionId then
8562           transVariableNamesOut(tempIndex) := engStProductionsTable(i).variable_name;
8563           tempIndex := tempIndex + 1;
8564         end if;
8565       end loop;
8566       exception
8567         when others then
8568           ame_util.runtimeException(packageNameIn => 'ame_engine',
8569                                     routineNameIn => 'getTransVariableNames',
8570                                     exceptionNumberIn => sqlcode,
8571                                     exceptionStringIn => sqlerrm);
8572           raise;
8573     end getTransVariableNames;
8574   procedure getTransVariableValues(transVariableValuesOut out nocopy ame_util.stringList) as
8575     tempIndex integer;
8576     begin
8577       tempIndex := 1;
8578       for i in 1 .. engStProductionsTable.count loop
8579         if engStProductionsTable(i).item_class = ame_util.headerItemClassName and
8580          engStProductionsTable(i).item_id = engTransactionId then
8581           transVariableValuesOut(tempIndex) := engStProductionsTable(i).variable_value;
8582           tempIndex := tempIndex + 1;
8583         end if;
8584       end loop;
8585       exception
8586         when others then
8587           ame_util.runtimeException(packageNameIn => 'ame_engine',
8588                                     routineNameIn => 'getTransVariableValues',
8589                                     exceptionNumberIn => sqlcode,
8590                                     exceptionStringIn => sqlerrm);
8591           raise;
8592     end getTransVariableValues;
8593   procedure getVariableNames(variableNamesOut out nocopy ame_util.stringList) as
8594     begin
8595       for i in 1 .. engStVariableNames.count loop
8596         variableNamesOut(i) := engStVariableNames(i);
8597       end loop;
8598       exception
8599         when others then
8600           ame_util.runtimeException(packageNameIn => 'ame_engine',
8601                                     routineNameIn => 'getVariableNames',
8602                                     exceptionNumberIn => sqlcode,
8603                                     exceptionStringIn => sqlerrm);
8604           raise;
8605     end getVariableNames;
8606   procedure getVariableValues(variableValuesOut out nocopy ame_util.stringList) as
8607     begin
8608       for i in 1 .. engStVariableValues.count loop
8609         variableValuesOut(i) := engStVariableValues(i);
8610       end loop;
8611       exception
8612         when others then
8613           ame_util.runtimeException(packageNameIn => 'ame_engine',
8614                                     routineNameIn => 'getVariableValues',
8615                                     exceptionNumberIn => sqlcode,
8616                                     exceptionStringIn => sqlerrm);
8617           raise;
8618     end getVariableValues;
8619   /* initializePlsqlContext is for amem0013.sql backwards compatibility only.  Do not use it elsewhere. */
8620   procedure initializePlsqlContext(ameApplicationIdIn in integer default null,
8621                                    fndApplicationIdIn in integer default null,
8622                                    transactionIdIn in varchar2 default null,
8623                                    transactionTypeIdIn in varchar2 default null,
8624                                    fetchConfigVarsIn in boolean default true,
8625                                    fetchOldApproversIn in boolean default true,
8626                                    fetchInsertionsIn in boolean default true,
8627                                    fetchDeletionsIn in boolean default true,
8628                                    fetchAttributeValuesIn in boolean default true,
8629                                    fetchInactiveAttValuesIn in boolean default false) as
8630     begin
8631       setContext(isTestTransactionIn => false,
8632                  isLocalTransactionIn => true,
8633                  fetchConfigVarsIn => true,
8634                  fetchOldApproversIn => true,
8635                  fetchInsertionsIn => true,
8636                  fetchDeletionsIn => true,
8637                  fetchAttributeValuesIn => true,
8638                  fetchInactiveAttValuesIn => false,
8639                  processProductionActionsIn => false,
8640                  processProductionRulesIn => false,
8641                  updateCurrentApproverListIn => true,
8642                  updateOldApproverListIn => true,
8643                  processPrioritiesIn => true,
8644                  prepareItemDataIn => false,
8645                  prepareRuleIdsIn => false,
8646                  prepareRuleDescsIn => false,
8647                  prepareApproverTreeIn => false,
8648                  transactionIdIn => transactionIdIn,
8649                  ameApplicationIdIn => ameApplicationIdIn,
8650                  fndApplicationIdIn => null,
8651                  transactionTypeIdIn => transactionTypeIdIn);
8652       exception
8653         when others then
8654           ame_util.runtimeException(packageNameIn => 'ame_engine',
8655                                     routineNameIn => 'initializePlsqlContext',
8656                                     exceptionNumberIn => sqlcode,
8657                                     exceptionStringIn => sqlerrm);
8658           raise;
8659     end initializePlsqlContext;
8660   procedure updateDeviationList( sourceIndexIn in number
8661                               ,targetIndexIn in number) as
8662   begin
8663    if engDeviationResultList.exists(sourceIndexIn) then
8664      engDeviationResultList(targetIndexIn) := engDeviationResultList(sourceIndexIn);
8665      engDeviationResultList.delete(sourceIndexIn);
8666    else
8667      return;
8668    end if;
8669   exception
8670     when others then
8671       ame_util.runtimeException(packageNameIn => 'ame_engine',
8672                                 routineNameIn => 'updateDeviationList',
8673                                 exceptionNumberIn => sqlcode,
8674                                 exceptionStringIn => sqlerrm);
8675   end updateDeviationList;
8676   procedure insertApprover(indexIn in integer,
8677                            approverIn in ame_util.approverRecord2,
8678                            adjustMemberOrderNumbersIn in boolean default false,
8679                            approverLocationIn in boolean default ame_util.lastAmongEquals,
8680                            inserteeIndexIn in number default null,
8681                            currentInsIndex in integer default null) as
8682     engStApproversCount integer;
8683     errorCode integer;
8684     errorMessage ame_util.longestStringType;
8685     indexException exception;
8686     lastIndex integer;
8687     nextIndex integer;
8688     nextIndexInChain boolean;
8689     previousIndex integer;
8690     previousIndexInChain boolean;
8691     tempVotingRegime     varchar2(1);
8692     approverTreeIndex    integer;
8693     begin
8694       checkApprover(approverIn => approverIn);
8695       engStApproversCount := engStApprovers.count;
8696       if(indexIn < 1 or
8697          indexIn > engStApproversCount + 1) then
8698         raise indexException;
8699       end if;
8700       nextIndex := indexIn + 1;
8701       previousIndex := indexIn - 1;
8702       if(engStApproversCount < nextIndex) then
8703         lastIndex := engStApproversCount;
8704       else
8705         lastIndex := nextIndex;
8706       end if;
8707       /* Move any existing approvers at and above the target index. */
8708       /*
8709         It's necessary to initialize a new record at the end of engStApprovers,
8710         for ame_util.copyApproverRecord2 to work in the loop below.
8711       */
8712       engStApprovers(engStApproversCount + 1) := ame_util.emptyApproverRecord2;
8713       for i in reverse indexIn .. engStApproversCount loop
8714         ame_util.copyApproverRecord2(approverRecord2In => engStApprovers(i),
8715                                      approverRecord2Out => engStApprovers(i + 1));
8716         for j in 1..engInsApproverIndex.count loop
8717           if engInsApproverIndex(j) = i then
8718              engInsApproverIndex(j) := null;
8719              engInsApproverIndex(j) := i+1;
8720           end if;
8721         end loop;
8722       end loop;
8723       /* Copy the input approver to the target index. */
8724       ame_util.copyApproverRecord2(approverRecord2In => approverIn,
8725                                    approverRecord2Out => engStApprovers(indexIn));
8726       /*
8727        If the status is not available in ame_temp_insertions get it from
8728        ame_temp_old_approver_lists
8729       */
8730       if engStApprovers(indexIn).approval_status is null then
8731         engStApprovers(indexIn).approval_status :=  getHandlerApprovalStatus(approverIn => engStApprovers(indexIn));
8732       end if;
8733       engStApproversCount := engStApproversCount + 1;
8734       /* Optionally adjust member_order_number values in the target group or chain. */
8735       if(adjustMemberOrderNumbersIn) then
8736         if(indexIn = 1 or
8737            engStApprovers(previousIndex).group_or_chain_id <> approverIn.group_or_chain_id or
8738            engStApprovers(previousIndex).action_type_id <> approverIn.action_type_id or
8739            engStApprovers(previousIndex).item_id <> approverIn.item_id or
8740            engStApprovers(previousIndex).item_class <> approverIn.item_class) then
8741           previousIndexInChain := false;
8742         else
8743           previousIndexInChain := true;
8744         end if;
8745         if(indexIn = engStApprovers.count or
8746            engStApprovers(nextIndex).group_or_chain_id <> approverIn.group_or_chain_id or
8747            engStApprovers(nextIndex).action_type_id <> approverIn.action_type_id or
8748            engStApprovers(nextIndex).item_id <> approverIn.item_id or
8749            engStApprovers(nextIndex).item_class <> approverIn.item_class) then
8750           nextIndexInChain := false;
8751         else
8752           nextIndexInChain := true;
8753         end if;
8754         if(previousIndexInChain) then
8755           if(nextIndexInChain) then
8756             if(engStApprovers(previousIndex).member_order_number =
8757                engStApprovers(nextIndex).member_order_number) then
8758               engStApprovers(indexIn).member_order_number := engStApprovers(previousIndex).member_order_number;
8759             else
8760               engStApprovers(indexIn).member_order_number := engStApprovers(previousIndex).member_order_number + 1;
8761               for i in nextIndex .. engStApproversCount loop
8762                 if(engStApprovers(i).item_class <> engStApprovers(indexIn).item_class or
8763                    engStApprovers(i).item_id <> engStApprovers(indexIn).item_id or
8764                    engStApprovers(i).action_type_id <> engStApprovers(indexIn).action_type_id or
8765                    engStApprovers(i).group_or_chain_id <> engStApprovers(indexIn).group_or_chain_id) then
8766                   exit;
8767                 end if;
8768                 engStApprovers(i).member_order_number := engStApprovers(i).member_order_number + 1;
8769               end loop;
8770             end if;
8771           else
8772             if(engStApprovers(previousIndex).approval_status in
8773              (ame_util.approveAndForwardStatus, ame_util.forwardStatus)) then
8774               if(engActionTypeNames(engStApprovers(previousIndex).action_type_id) in
8775                       (ame_util.groupChainApprovalTypeName
8776                       ,ame_util.preApprovalTypeName
8777                       ,ame_util.postApprovalTypeName )) then
8778                 select voting_regime
8779                   into tempVotingRegime
8780                   from ame_approval_group_config
8781                  where approval_group_id = engStApprovers(previousIndex).group_or_chain_id
8782                    and application_id = engAmeApplicationId
8783                    and sysdate between start_date and nvl(end_Date - (1/86400), sysdate);
8784                 if(tempVotingRegime not in (ame_util.serializedVoting
8785                                            ,ame_util.orderNumberVoting)) then
8786                   engStApprovers(indexIn).member_order_number := 1;
8787                 else
8788                   engStApprovers(indexIn).member_order_number := engStApprovers(previousIndex).member_order_number + 1;
8789                 end if;
8790               else
8791                 if(engActionTypeVotingRegimes(engStApprovers(previousIndex).action_type_id) <>
8792                          ame_util.serializedVoting) then
8793                   engStApprovers(indexIn).member_order_number := 1;
8794                 else
8795                   engStApprovers(indexIn).member_order_number := engStApprovers(previousIndex).member_order_number + 1;
8796                 end if;
8797               end if;
8798             else
8799               engStApprovers(indexIn).member_order_number := engStApprovers(previousIndex).member_order_number + 1;
8800             end if;
8801           end if;
8802         else
8803           if(nextIndexInChain) then
8804             engStApprovers(indexIn).member_order_number := engStApprovers(nextIndex).member_order_number - 1;
8805           else
8806             engStApprovers(indexIn).member_order_number := 1;
8807           end if;
8808         end if;
8809       end if;
8810       if engPrepareApproverTree then
8811         if engStApproversTree.count = 0 then
8812         /* If there are no approvers in tree just add the approver                  */
8813           if inserteeIndexIn is not null then
8814             engTempReason := engInsertionReasonList(inserteeIndexIn);
8815             engTempDate := engInsertionDateList(inserteeIndexIn);
8816           end if;
8817           addApproverToTree
8818             (approverRecordIn    => engStApprovers(indexIn)
8819             ,approverIndexIn     => indexIn
8820             ,approverLocationIn  => ame_util.lastAmongEquals);
8821           if currentInsIndex is not null then
8822             engInsApproverIndex(currentInsIndex) := indexIn;
8823           end if;
8824         else
8825         /* If there exists approvers in the tree then if adjustMemberOrderNumbersIn */
8826         /* is true update the member order number in the tree                       */
8827         /* Add the approver to tree                                                 */
8828           if adjustMemberOrderNumbersIn then
8829             approverTreeIndex := engStApproversTree.first;
8830             loop
8831               if engStApproversTree(approverTreeIndex).approver_index >= indexIn then
8832                 engStApproversTree(approverTreeIndex).order_number
8833                      := engStApprovers(engStApproversTree(approverTreeIndex).approver_index + 1).member_order_number;
8834               end if;
8835               exit when approverTreeIndex = engStApproversTree.last;
8836               approverTreeIndex := engStApproversTree.next(approverTreeIndex);
8837             end loop;
8838           end if;
8839           approverTreeIndex := engStApproversTree.first;
8840           loop
8841             if engStApproversTree(approverTreeIndex).approver_index >= indexIn then
8842               engStApproversTree(approverTreeIndex).approver_index := engStApproversTree(approverTreeIndex).approver_index + 1;
8843             end if;
8844             exit when approverTreeIndex = engStApproversTree.last;
8845             approverTreeIndex := engStApproversTree.next(approverTreeIndex);
8846           end loop;
8847           if inserteeIndexIn is not null then
8848             engTempReason := engInsertionReasonList(inserteeIndexIn);
8849             engTempDate := engInsertionDateList(inserteeIndexIn);
8850           end if;
8851           addApproverToTree
8852             (approverRecordIn    => engStApprovers(indexIn)
8853             ,approverIndexIn     => indexIn
8854             ,approverLocationIn  => approverLocationIn);
8855           if currentInsIndex is not null then
8856             engInsApproverIndex(currentInsIndex) := indexIn;
8857           end if;
8858         end if;
8859       end if;
8860       exception
8861         when indexException then
8862           errorCode := -20001;
8863           errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
8864                                               messageNameIn => 'AME_400686_ENG_IDX_OUT_OF_BOU');
8865           ame_util.runtimeException(packageNameIn => 'ame_engine',
8866                                     routineNameIn => 'insertApprover',
8867                                     exceptionNumberIn => errorCode,
8868                                     exceptionStringIn => errorMessage);
8869           raise_application_error(errorCode,
8870                                   errorMessage);
8871         when others then
8872           ame_util.runtimeException(packageNameIn => 'ame_engine',
8873                                     routineNameIn => 'insertApprover',
8874                                     exceptionNumberIn => sqlcode,
8875                                     exceptionStringIn => sqlerrm);
8876           raise;
8877     end insertApprover;
8878   procedure insertApprovers(firstIndexIn in integer,
8879                             approversIn in ame_util.approversTable2) as
8880     approversInCount integer;
8881     engStApproversCount integer;
8882     errorCode integer;
8883     errorMessage ame_util.longestStringType;
8884     indexException exception;
8885     lastIndex integer;
8886     newTreeNode ame_util.approverTreeRecord;
8887     newTreeNodeIndex integer;
8888     siblingTreeNodeIndex integer;
8889     tempIndex integer;
8890     loopIndex integer;
8891     begin
8892       if(firstIndexIn < 1 or
8893          firstIndexIn > engStApprovers.count + 1) then
8894         raise indexException;
8895       end if;
8896       approversInCount := approversIn.count;
8897       engStApproversCount := engStApprovers.count;
8898       /* This code was modified to fix the BUG:(4093937) */
8899       /* Issue 1 in the list of bugs found during the implementation of the */
8900       /* asynchronous parallel approver functionality */
8901       lastIndex := engStApproversCount;
8902       /* Move any existing approvers at and above firstIndexIn. */
8903       for i in reverse firstIndexIn .. lastIndex loop
8904         ame_util.copyApproverRecord2(approverRecord2In => engStApprovers(i),
8905                                      approverRecord2Out => engStApprovers(i + approversInCount));
8906       end loop;
8907       /* Copy the input approvers to the target indexes. */
8908       tempIndex := firstIndexIn; /* post-increment */
8909       for i in 1 .. approversInCount loop
8910         ame_util.copyApproverRecord2(approverRecord2In => approversIn(i),
8911                                      approverRecord2Out => engStApprovers(tempIndex));
8912         tempIndex := tempIndex + 1;
8913       end loop;
8914       /* Insert the new approvers to the tree */
8915       if engPrepareApproverTree then
8916         /* Approvers Tree is sparse */
8917         loopIndex := engStApproversTree.last;
8918         loop
8919           if engStApproversTree(loopIndex).approver_index >= firstIndexIn then
8920             engStApproversTree(loopIndex).approver_index
8921                                  := engStApproversTree(loopIndex).approver_index + approversIn.count;
8922           elsif engStApproversTree(loopIndex).approver_index = firstIndexIn - 1 then
8923             siblingTreeNodeIndex := engStApproversTree(loopIndex).sibling_index;
8924             for j in reverse 1 .. approversIn.count loop
8925               newTreeNode.parent_index := engStApproversTree(loopIndex).parent_index;
8926               newTreeNode.sibling_index := siblingTreeNodeIndex;
8927               newTreeNode.child_index := ame_util.noChildIndex;
8928               newTreeNode.order_number := approversIn(j).member_order_number;
8929               newTreeNode.approver_index := engStApproversTree(loopIndex).approver_index + j ;
8930               newTreeNode.tree_level_id := approversIn(j).name;
8931               newTreeNode.is_suspended := ame_util.booleanFalse;
8932               newTreeNode.tree_level := 6;
8933               newTreeNodeIndex := engStApproversTree.last + 1;
8934               engStApproversTree(newTreeNodeIndex) := newTreeNode;
8935               siblingTreeNodeIndex := newTreeNodeIndex;
8936             end loop;
8937             engStApproversTree(loopIndex).sibling_index := siblingTreeNodeIndex;
8938           end if;
8939           exit when engStApproversTree.first = loopIndex;
8940           loopIndex := engStApproversTree.prior(loopIndex);
8941         end loop;
8942       end if;
8943       exception
8944         when indexException then
8945           errorCode := -20001;
8946           errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
8947                                               messageNameIn => 'AME_400687_ENG_FIDX_OUT_OF_BOU');
8948           ame_util.runtimeException(packageNameIn => 'ame_engine',
8949                                     routineNameIn => 'insertApprovers',
8950                                     exceptionNumberIn => errorCode,
8951                                     exceptionStringIn => errorMessage);
8952           raise_application_error(errorCode,
8953                                   errorMessage);
8954         when others then
8955           ame_util.runtimeException(packageNameIn => 'ame_engine',
8956                                     routineNameIn => 'insertApprovers',
8957                                     exceptionNumberIn => sqlcode,
8958                                     exceptionStringIn => sqlerrm);
8959           raise;
8960     end insertApprovers;
8961   procedure insertIntoTransApprovalHistory
8962               (transactionIdIn  ame_trans_approval_history.transaction_id%type
8963               ,applicationIdIn  ame_trans_approval_history.application_id%type
8964               ,orderNumberIn    ame_trans_approval_history.order_number%type
8965               ,nameIn           ame_trans_approval_history.name%type
8966               ,appCategoryIn    ame_trans_approval_history.approver_category%type
8967               ,itemClassIn      ame_trans_approval_history.item_class%type
8968               ,itemIdIn         ame_trans_approval_history.item_id%type
8969               ,actionTypeIdIn   ame_trans_approval_history.action_type_id%type
8970               ,authorityIn      ame_trans_approval_history.authority%type
8971               ,statusIn         ame_trans_approval_history.status%type
8972               ,grpOrChainIdIn   ame_trans_approval_history.group_or_chain_id%type
8973               ,occurrenceIn     ame_trans_approval_history.occurrence%type
8974               ,apiInsertionIn   ame_trans_approval_history.api_insertion%type
8975               ,memberorderNumberIn ame_trans_approval_history.member_order_number%type
8976               ,notificationIdIn ame_trans_approval_history.notification_id%type
8977               ,userCommentsIn   ame_trans_approval_history.user_comments%type
8978               ,dateClearedIn    ame_trans_approval_history.date_cleared%type
8979               ,historyTypeIn    varchar2) as
8980     tempTransHistoryId ame_trans_approval_history.trans_history_id%type;
8981     tempItemClass      ame_trans_approval_history.item_class%type;
8982     tempItemId         ame_trans_approval_history.item_id%type;
8983     tempOrderNumber    ame_trans_approval_history.order_number%type;
8984     tempAuthority      ame_trans_approval_history.authority%type;
8985     tempActionTypeId   ame_trans_approval_history.action_type_id%type;
8986     tempGroupOrChainId ame_trans_approval_history.group_or_chain_id%type;
8987     tempOccurrence     ame_trans_approval_history.occurrence%type;
8988     tempApiInsertion   ame_trans_approval_history.api_insertion%type;
8989     tempMemberOrderNumber ame_trans_approval_history.member_order_number%type;
8990     tempName           ame_trans_approval_history.name%type;
8991     approvers          ame_util.approversTable2;
8992     begin
8993       tempName := nameIn;
8994       if historyTypeIn = 'BEATBYFIRSTRESPONDER' then
8995         ame_engine.getApprovers(approversOut => approvers);
8996         for i in 1 .. approvers.count loop
8997           if (approvers(i).name <> nameIn or approvers(i).occurrence <> occurrenceIn)
8998             and approvers(i).item_class = itemClassIn
8999             and approvers(i).item_id = itemIdIn
9000             and approvers(i).action_type_id = actionTypeIdIn
9001             and approvers(i).group_or_chain_id = grpOrChainIdIn
9002             and approvers(i).approver_category = ame_util.approvalApproverCategory
9003             and approvers(i).approval_status = ame_util.notifiedStatus
9004           then
9005             select ame_trans_approval_history_s.nextval
9006               into tempTransHistoryId
9007               from dual;
9008             insert into AME_TRANS_APPROVAL_HISTORY
9009                 (TRANS_HISTORY_ID
9010                 ,TRANSACTION_ID
9011                 ,APPLICATION_ID
9012                 ,ROW_TIMESTAMP
9013                 ,ORDER_NUMBER
9014                 ,NAME
9015                 ,APPROVER_CATEGORY
9016                 ,ITEM_CLASS
9017                 ,ITEM_ID
9018                 ,ACTION_TYPE_ID
9019                 ,AUTHORITY
9020                 ,STATUS
9021                 ,GROUP_OR_CHAIN_ID
9022                 ,OCCURRENCE
9023                 ,API_INSERTION
9024                 ,MEMBER_ORDER_NUMBER
9025                 ,NOTIFICATION_ID
9026                 ,USER_COMMENTS
9027                 ,DATE_CLEARED
9028                 )select tempTransHistoryId
9029                        ,transactionIdIn
9030                        ,applicationIdIn
9031                        ,sysdate
9032                        ,approvers(i).approver_order_number
9033                        ,approvers(i).name
9034                        ,approvers(i).approver_category
9035                        ,approvers(i).item_class
9036                        ,approvers(i).item_id
9037                        ,approvers(i).action_type_id
9038                        ,approvers(i).authority
9039                        ,ame_util.beatByFirstResponderStatus
9040                        ,approvers(i).group_or_chain_id
9041                        ,approvers(i).occurrence
9042                        ,approvers(i).api_insertion
9043                        ,approvers(i).member_order_number
9044                        ,notificationIdIn
9045                        ,null
9046                        ,null
9047                    from dual;
9048           end if;
9049         end loop;
9050         return;
9051       end if;
9052       select ame_trans_approval_history_s.nextval
9053         into tempTransHistoryId
9054         from dual;
9055       if historyTypeIn = 'APPROVERPRESENT' then
9056         insert into AME_TRANS_APPROVAL_HISTORY
9057                 (TRANS_HISTORY_ID
9058                 ,TRANSACTION_ID
9059                 ,APPLICATION_ID
9060                 ,ROW_TIMESTAMP
9061                 ,ORDER_NUMBER
9062                 ,NAME
9063                 ,APPROVER_CATEGORY
9064                 ,ITEM_CLASS
9065                 ,ITEM_ID
9066                 ,ACTION_TYPE_ID
9067                 ,AUTHORITY
9068                 ,STATUS
9069                 ,GROUP_OR_CHAIN_ID
9070                 ,OCCURRENCE
9071                 ,API_INSERTION
9072                 ,MEMBER_ORDER_NUMBER
9073                 ,NOTIFICATION_ID
9074                 ,USER_COMMENTS
9075                 ,DATE_CLEARED
9076                 )values
9077                 (tempTransHistoryId
9078                 ,transactionIdIn
9079                 ,applicationIdIn
9080                 ,sysdate
9081                 ,orderNumberIn
9082                 ,nameIn
9083                 ,appCategoryIn
9084                 ,itemClassIn
9085                 ,itemIdIn
9086                 ,actionTypeIdIn
9087                 ,authorityIn
9088                 ,statusIn
9089                 ,grpOrChainIdIn
9090                 ,occurrenceIn
9091                 ,apiInsertionIn
9092                 ,memberorderNumberIn
9093                 ,notificationIdIn
9094                 ,userCommentsIn
9095                 ,dateClearedIn);
9096       else
9097         begin
9098           select atah.item_class item_class
9099                 ,atah.item_id item_id
9100                 ,atah.order_number order_number
9101                 ,atah.authority authority
9102                 ,atah.action_type_id action_type_id
9103                 ,atah.group_or_chain_id group_or_chain_id
9104                 ,atah.occurrence occurrence
9105                 ,atah.api_insertion api_insertion
9106                 ,atah.member_order_number member_order_number
9107             into tempItemClass
9108                 ,tempItemId
9109                 ,tempOrderNumber
9110                 ,tempAuthority
9111                 ,tempActionTypeId
9112                 ,tempGroupOrChainId
9113                 ,tempOccurrence
9114                 ,tempApiInsertion
9115                 ,tempMemberOrderNumber
9116             from ame_trans_approval_history atah
9117                 ,fnd_lookups lookup
9118                 ,fnd_lookups lookup2
9119                 ,ame_approval_groups apg
9120            where atah.date_cleared is null
9121              and atah.transaction_id = transactionIdIn
9122              and atah.application_id = applicationIdIn
9123              and atah.name = tempName
9124              and atah.trans_history_id =
9125                    (select max(b.trans_history_id)
9126                       from ame_trans_approval_history b
9127                      where atah.transaction_id = b.transaction_id
9128                        and atah.application_id = b.application_id
9129                        and atah.name = b.name
9130                        and atah.approver_category = b.approver_category
9131                        and atah.item_class = b.item_class
9132                        and atah.item_id = b.item_id
9133                        and atah.action_type_id = b.action_type_id
9134                        and atah.authority = b.authority
9135                        and atah.group_or_chain_id = b.group_or_chain_id
9136                        and atah.occurrence = b.occurrence
9137                        and b.date_cleared is null )
9138              and lookup.lookup_type = 'AME_SUBLIST_TYPES'
9139              and lookup.lookup_code = atah.authority
9140              and lookup2.lookup_type = 'AME_APPROVAL_STATUS'
9141              and lookup2.lookup_code = atah.status
9142              and apg.approval_group_id(+) = atah.group_or_chain_id
9143              and sysdate between nvl(apg.start_date,sysdate) and nvl(apg.end_date,sysdate);
9144         exception
9145           when no_data_found then
9146             tempItemClass      := '$AME_INVALID_ITEM_CLASS$';
9147             tempItemId         := '$AME_INVALID_ITEM$';
9148             tempOrderNumber    := 0;
9149             tempAuthority      := 'Y';
9150             tempActionTypeId   := ame_util.nullHistoryActionTypeId;
9151             tempGroupOrChainId := ame_util.nullHistoryGroupOrChainId;
9152             tempOccurrence     := ame_util.nullHistoryOccurrence;
9153             tempApiInsertion   := null;
9154             tempMemberOrderNumber := null;
9155         end;
9156         if orderNumberIn is not null then
9157           tempOrderNumber := orderNumberIn;
9158         end if;
9159         if itemClassIn is not null then
9160           tempItemClass := itemClassIn;
9161         end if;
9162         if itemIdIn is not null then
9163           tempItemId := itemIdIn;
9164         end if;
9165         if grpOrChainIdIn is not null then
9166           tempGroupOrChainId := grpOrChainIdIn;
9167         end if;
9168         if authorityIn is not null then
9169           tempAuthority := authorityIn;
9170         end if;
9171         if actionTypeIdIn is not null then
9172           tempActionTypeId := actionTypeIdIn;
9173         end if;
9174         if occurrenceIn is not null then
9175           tempOccurrence := occurrenceIn;
9176         end if;
9177         if apiInsertionIn is not null then
9178           tempApiInsertion := apiInsertionIn;
9179         end if;
9180         if memberorderNumberIn is not null then
9181           tempMemberOrderNumber := memberorderNumberIn;
9182         end if;
9183         insert into AME_TRANS_APPROVAL_HISTORY
9184                 (TRANS_HISTORY_ID
9185                 ,TRANSACTION_ID
9186                 ,APPLICATION_ID
9187                 ,ROW_TIMESTAMP
9188                 ,ORDER_NUMBER
9189                 ,NAME
9190                 ,APPROVER_CATEGORY
9191                 ,ITEM_CLASS
9192                 ,ITEM_ID
9193                 ,ACTION_TYPE_ID
9194                 ,AUTHORITY
9195                 ,STATUS
9196                 ,GROUP_OR_CHAIN_ID
9197                 ,OCCURRENCE
9198                 ,API_INSERTION
9199                 ,MEMBER_ORDER_NUMBER
9200                 ,NOTIFICATION_ID
9201                 ,USER_COMMENTS
9202                 ,DATE_CLEARED
9203                ) values
9204                (tempTransHistoryId
9205                ,transactionIdIn
9206                ,applicationIdIn
9207                ,sysdate
9208                ,tempOrderNumber
9209                ,nameIn
9210                ,appCategoryIn
9211                ,tempItemClass
9212                ,tempItemId
9213                ,tempActionTypeId
9214                ,tempAuthority
9215                ,statusIn
9216                ,tempGroupOrChainId
9217                ,tempOccurrence
9218                ,tempApiInsertion
9219                ,tempMemberOrderNumber
9220                ,notificationIdIn
9221                ,userCommentsIn
9222                ,dateClearedIn
9223                );
9224       end if;
9225       exception
9226         when others then
9227           ame_util.runtimeException(packageNameIn => 'ame_engine',
9228                                     routineNameIn => 'insertIntoTransApprovalHistory',
9229                                     exceptionNumberIn => sqlcode,
9230                                     exceptionStringIn => sqlerrm);
9231 
9232     end insertIntoTransApprovalHistory;
9233   procedure lockTransaction(fndApplicationIdIn in integer,
9234                             transactionIdIn in varchar2,
9235                             transactionTypeIdIn in varchar2 default null) as
9236     tempTransIsLocked varchar2(2);
9237     cursor IsEngLocked is
9238       select 'Y'
9239         from ame_temp_trans_locks
9240        where fnd_application_id = fndApplicationIdIn
9241          and transaction_id = transactionIdIn
9242          and transaction_type_id = transactionTypeIdIn;
9243     begin
9244       /*
9245         The ame_temp_trans_locks_pk unique index will prevent the following insert from occurring
9246         if another row has already been inserted into ame_temp_trans_locks with the same
9247         fnd_application_id, transaction_type_id, and transaction_id values (even though the other
9248         insert is not committed).
9249       */
9250       tempTransIsLocked := null;
9251       if(engTransactionIsLocked) then
9252         return;
9253       end if;
9254       open IsEngLocked;
9255       fetch IsEngLocked into tempTransIsLocked;
9256       close IsEngLocked;
9257       if tempTransIsLocked = 'Y' then
9258         return;
9259       end if;
9260       insert into ame_temp_trans_locks(fnd_application_id,
9261                                        transaction_type_id,
9262                                        transaction_id,
9263                                        row_timestamp) values(
9264                                        fndApplicationIdIn,
9265                                        transactionTypeIdIn,
9266                                        transactionIdIn,
9267                                        sysdate);
9268       engTransactionIsLocked := true;
9269       exception
9270         when others then
9271           ame_util.runtimeException(packageNameIn => 'ame_engine',
9272                                     routineNameIn => 'lockTransaction',
9273                                     exceptionNumberIn => sqlcode,
9274                                     exceptionStringIn => sqlerrm);
9275           raise;
9276     end lockTransaction;
9277   procedure logTransaction as
9278     tempCount integer:= null;
9279     tempTransSeqId number;
9280     begin
9281       /* Log the transaction for eventual purging from the temp tables. */
9282       select count(*)
9283         into tempCount
9284         from ame_temp_transactions
9285         where
9286           application_id = engAmeApplicationId and
9287           transaction_id = engTransactionId and
9288           rownum < 2; /* Avoids second fetch otherwise required by ANSI standard to check for too many rows. */
9289       if(tempCount = 0) then
9290         select ame_temp_transactions_s.nextval into tempTransSeqId from dual;
9291         insert into ame_temp_transactions(
9292           application_id,
9293           transaction_id,
9294           row_timestamp,
9295           temp_transactions_id
9296           ) values(
9297             engAmeApplicationId,
9298             engTransactionId,
9299             sysdate,
9300             tempTransSeqId); /* Don't use engEffectiveRuleDate here. */
9301       end if;
9302       exception
9303         when others then
9304           ame_util.runtimeException(packageNameIn => 'ame_engine',
9305                                     routineNameIn => 'logTransaction',
9306                                     exceptionNumberIn => sqlcode,
9307                                     exceptionStringIn => sqlerrm);
9308           raise;
9309     end logTransaction;
9310   procedure parseFields(stringIn in varchar2,
9311                         fieldsOut out nocopy ame_util.longStringList) as
9312     fieldEnd integer;
9313     fieldIndex integer;
9314     fieldStart integer;
9315     stringLength integer;
9316     begin
9317       stringLength := lengthb(stringIn);
9318       fieldStart := 1;
9319       fieldIndex := 1; /* post-increment */
9320       loop
9321         fieldEnd := instrb(stringIn, ame_util.fieldDelimiter, fieldStart, 1);
9322         if(fieldEnd = 0) then
9323           fieldsOut(fieldIndex) := substrb(stringIn, fieldStart);
9324           exit;
9325         end if;
9326         fieldsOut(fieldIndex) := substrb(stringIn, fieldStart, fieldEnd - fieldStart);
9327         fieldIndex := fieldIndex + 1;
9328         fieldStart := fieldEnd + 1;
9329       end loop;
9330       exception
9331         when others then
9332           ame_util.runtimeException(packageNameIn => 'ame_engine',
9333                                     routineNameIn => 'parseFields',
9334                                     exceptionNumberIn => sqlcode,
9335                                     exceptionStringIn => sqlerrm);
9336           raise;
9337     end parseFields;
9338   procedure parseForwardingBehaviors(forwardingBehaviorsIn in varchar2) as
9339     startPosition integer;
9340     valueLength integer;
9341     begin
9342       startPosition := 1;
9343       for i in 1 .. 8 loop
9344         if(i = 8) then
9345           valueLength := lengthb(substrb(forwardingBehaviorsIn, startPosition));
9346         else
9347           valueLength := instrb(forwardingBehaviorsIn, ':', startPosition + 1, 1) - startPosition;
9348         end if;
9349         engForwardingBehaviors(i) := substrb(forwardingBehaviorsIn, startPosition, valueLength);
9350         startPosition := startPosition + valueLength + 1;
9351       end loop;
9352       exception
9353         when others then
9354           ame_util.runtimeException(packageNameIn => 'ame_engine',
9355                                     routineNameIn => 'parseForwardingBehaviors',
9356                                     exceptionNumberIn => sqlcode,
9357                                     exceptionStringIn => sqlerrm);
9358           raise;
9359     end parseForwardingBehaviors;
9360   procedure parsePriorityModes(priorityModesIn in varchar2) as
9361     currentValue ame_util.stringType;
9362     endPosition integer;
9363     startPosition integer;
9364     underscorePosition integer;
9365     begin
9366       /*
9367         The i - 1 indexes on the left side of the assignments account
9368         for the rule-type constants starting at zero.
9369       */
9370       startPosition := 1;
9371       for i in 1 .. 8 loop
9372         if(i < 8) then
9373           endPosition := instrb(priorityModesIn, ':', startPosition, 1) - 1;
9374         else
9375           endPosition := lengthb(priorityModesIn);
9376         end if;
9377         currentValue := substrb(priorityModesIn, startPosition, endPosition - startPosition + 1);
9378         underscorePosition := instrb(currentValue, '_', 1, 1);
9379         if(underscorePosition = 0) then
9380           engPriorityModes(i - 1) := ame_util.disabledRulePriority;
9381           engPriorityThresholds(i - 1) := null;
9382         else
9383           engPriorityThresholds(i - 1) := to_number(substrb(currentValue, underscorePosition + 1));
9384           if(instrb(currentValue, ame_util.absoluteRulePriority, 1, 1) > 0) then
9385             engPriorityModes(i - 1) := ame_util.absoluteRulePriority;
9386           else
9387             engPriorityModes(i - 1) := ame_util.relativeRulePriority;
9388           end if;
9389         end if;
9390         startPosition := endPosition + 2;
9391       end loop;
9392       exception
9393         when others then
9394           ame_util.runtimeException(packageNameIn => 'ame_engine',
9395                                     routineNameIn => 'parsePriorityModes',
9396                                     exceptionNumberIn => sqlcode,
9397                                     exceptionStringIn => sqlerrm);
9398           raise;
9399     end parsePriorityModes;
9400   procedure populateEngStVariables as
9401     headerItemRejected boolean;
9402     itemIds            ame_util.stringList;
9403     itemClasses        ame_util.stringList;
9404     tempItemClass      ame_util.stringType;
9405     tempItemId         ame_util.stringType;
9406     tempItemIndex      integer;
9407     tempPseudoBoolean  ame_util.charType;
9408     stoppingRule       ame_util.stringType;
9409     itemRejected       boolean;
9410     tempCount          integer;
9411     begin
9412       /*
9413         The procedure processRepeatedApprovers populates most of the engSt variables, to synchronize
9414         that work with the repeatedApprovers functionality, for efficiency.  This procedure just
9415         populates engStApprovalProcessCompleteYN, engStItemAppProcessCompleteYN, engStProductionIndexes,
9416         engStVariableNames, and engStVariableValues.  Note that this procedure should execute after
9417         processRepeatedApprovers, so it can treat repeated approvers as having approved in the
9418         calculation of the approval-process-complete values.
9419       */
9420       /* Initialize various values. */
9421       itemRejected := false;
9422       engStApprovalProcessCompleteYN := ame_util2.completeNoApprovers;
9423       for i in 1 .. engItemIds.count loop
9424         engStItemAppProcessCompleteYN(i) := ame_util2.completeNoApprovers;
9425       end loop;
9426       /* Handle the empty-approver-list case first. */
9427       if(engStApprovers.count = 0) then
9428         return;
9429       end if;
9430       /* get all itemclasses and itemids of current transaction */
9431       getAllItemClasses(itemClassNamesOut => itemClasses);
9432       getAllItemIds(itemIdsOut            => itemIds);
9433       /*
9434         The approver list is non-empty.  Set the process-complete values per the statuses in
9435         engStApprovers;
9436       */
9437       /* modified the values of approvalProcessCompleteYN as per bug 4411016 */
9438       /* Initialize the temp variables. */
9439       tempItemId := engStApprovers(1).item_id;
9440       tempItemClass := engStApprovers(1).item_class;
9441       for i in 1 .. itemIds.count loop
9442         if(itemIds(i) = tempItemId and itemClasses(i) = tempItemClass) then
9443           tempItemIndex := i;
9444           engStItemAppProcessCompleteYN(tempItemIndex) := ame_util2.completeFullyApproved;
9445           if engStApprovalProcessCompleteYN = ame_util2.completeNoApprovers then
9446             engStApprovalProcessCompleteYN := ame_util2.completeFullyApproved;
9447           end if;
9448           exit;
9449         end if;
9450       end loop;
9451       tempPseudoBoolean := ame_util.booleanTrue;
9452       /* Loop through the approvers. */
9453       for i in 1 .. engStApprovers.count loop
9454         /* Update the temp variables when the item changes. */
9455         if(engStApprovers(i).item_id <> tempItemId or
9456            engStApprovers(i).item_class <> tempItemClass) then
9457           tempItemId := engStApprovers(i).item_id;
9458           tempItemClass := engStApprovers(i).item_class;
9459           tempPseudoBoolean := ame_util.booleanTrue;
9460           for j in (tempItemIndex + 1) .. itemIds.count loop
9461             if(itemIds(j) = tempItemId and itemClasses(j) = tempItemClass) then
9462               tempItemIndex := j;
9463               engStItemAppProcessCompleteYN(tempItemIndex) := ame_util2.completeFullyApproved;
9464               if engStApprovalProcessCompleteYN = ame_util2.completeNoApprovers then
9465                 engStApprovalProcessCompleteYN := ame_util2.completeFullyApproved;
9466               end if;
9467               exit;
9468             end if;
9469           end loop;
9470         end if;
9471         /* Update the process-complete engSt variables as appropriate. */
9472         -- check for pending/yet to be notified approvers
9473         if(engStItemAppProcessCompleteYN(tempItemIndex) <> ame_util2.completeFullyRejected and
9474            ((engStApprovers(i).approver_category = ame_util.approvalApproverCategory and
9475              (engStApprovers(i).approval_status is null or
9476               engStApprovers(i).approval_status in (ame_util.nullStatus
9477                                                    ,ame_util.notifiedStatus
9478                                                    ,ame_util.repeatedStatus
9479                                                    ,ame_util.notifiedByRepeatedStatus))) or
9480             (engStApprovers(i).approver_category = ame_util.fyiApproverCategory and
9481              (engStApprovers(i).approval_status is null or
9482              engStApprovers(i).approval_status = ame_util.nullStatus)))) then
9483           if engStItemAppProcessCompleteYN(tempItemIndex) in (ame_util2.completeNoApprovers
9484                                                              ,ame_util2.completeFullyApproved) then
9485             engStItemAppProcessCompleteYN(tempItemIndex) := ame_util2.notCompleted;
9486             if engStApprovalProcessCompleteYN in (ame_util2.completeNoApprovers
9487                                                  ,ame_util2.completeFullyApproved) then
9488               engStApprovalProcessCompleteYN := ame_util2.notCompleted;
9489             end if;
9490           end if;
9491         end if;
9492         -- check for rejections
9493         if(engStApprovers(i).approver_category = ame_util.approvalApproverCategory and
9494            engStApprovers(i).approval_status in (ame_util.rejectStatus,ame_util.rejectedByRepeatedStatus)) then
9495           itemRejected := true;
9496           if tempItemClass = ame_util.headerItemClassName then
9497             headerItemRejected := true;
9498           end if;
9499           engStItemAppProcessCompleteYN(tempItemIndex) := ame_util2.completeFullyRejected;
9500         end if;
9501       end loop;
9502 
9503       if itemRejected then
9504         stoppingRule := ame_engine.getHeaderAttValue2
9505                           (attributeNameIn => ame_util.rejectionResponseAttribute);
9506         if stoppingRule is null or stoppingRule not in (ame_util.stopAllItems,ame_util.continueOtherSubItems,
9507                                                         ame_util.continueAllOtherItems) then
9508            stoppingRule := ame_util.stopAllItems;
9509         end if;
9510         -- When the stoppingRule is STOP_ALL_ITEMS or a header item got rejected then
9511         -- 1. The transaction as a whole is rejected.
9512         -- 2. Make all pending items approval status rejected.
9513         if stoppingRule = ame_util.stopAllItems or headerItemRejected then
9514           engStApprovalProcessCompleteYN := ame_util2.completeFullyRejected;
9515           --+
9516           for x in 1 .. itemIds.count loop
9517             if engStItemAppProcessCompleteYN(x) = ame_util2.notCompleted then
9518               engStItemAppProcessCompleteYN(x) := ame_util2.completeFullyRejected;
9519             end if;
9520           end loop;
9521           --+
9522         end if;
9523         -- When the stoppingRule is CONTINUE_OTHER_SUBORDINATE_ITEMS or
9524         -- CONTINUE_ALL_OTHER_ITEMS then
9525         -- 1. Reject header item if stoppingRule is CONTINUE_OTHER_SUBORDINATE_ITEMS
9526         --    and header item is pending.
9527         -- 2. Set the transaction level status to partially rejected by default.
9528         -- 3. If any other item is still pending set the approval status of
9529         --    transaction to pending status.
9530         -- 4. If the transaction level status is still partially rejected then
9531         --    check for complete rejection. Complete rejection will happen if all items
9532         --    are rejected or have no approvers.
9533         if stoppingRule = ame_util.continueOtherSubItems or
9534            stoppingRule = ame_util.continueAllOtherItems then
9535           if stoppingRule = ame_util.continueOtherSubItems then
9536             for x in 1 .. itemIds.count loop
9537               if itemClasses(x) = ame_util.headerItemClassName and
9538                  engStItemAppProcessCompleteYN(x) = ame_util2.notCompleted then
9539                 engStItemAppProcessCompleteYN(x) := ame_util2.completeFullyRejected;
9540                 exit;
9541               end if;
9542             end loop;
9543           end if;
9544           engStApprovalProcessCompleteYN := ame_util2.completePartiallyApproved;
9545           for x in 1 .. itemIds.count loop
9546             if engStItemAppProcessCompleteYN(x) = ame_util2.notCompleted then
9547               engStApprovalProcessCompleteYN := ame_util2.notCompleted;
9548               exit;
9549             end if;
9550           end loop;
9551           tempCount := 0;
9552           if engStApprovalProcessCompleteYN = ame_util2.completePartiallyApproved then
9553             for x in 1 .. itemIds.count loop
9554               if engStItemAppProcessCompleteYN(x) <> ame_util2.completeFullyRejected and
9555                  engStItemAppProcessCompleteYN(x) <> ame_util2.completeNoApprovers then
9556                 exit;
9557               end if;
9558               tempCount := tempCount + 1;
9559             end loop;
9560             if tempCount = itemIds.count then
9561               engStApprovalProcessCompleteYN := ame_util2.completeFullyRejected;
9562             end if;
9563           end if;
9564         end if;
9565       end if;
9566       exception
9567         when others then
9568           ame_util.runtimeException(packageNameIn => 'ame_engine',
9569                                     routineNameIn => 'populateEngStVariables',
9570                                     exceptionNumberIn => sqlcode,
9571                                     exceptionStringIn => sqlerrm);
9572           raise;
9573     end populateEngStVariables;
9574   procedure processAdHocInsertions as
9575     displacedInserteeIndexes ame_util.idList;
9576     engStApproversCount integer;
9577     parameterFields ame_util.longStringList;
9578     tempAnchorIndex integer;
9579     tempBoolean boolean;
9580     tempIndex integer;
9581     tempIndex2 integer;
9582     tempItemClass ame_temp_insertions.item_class%type;
9583     tempItemId ame_temp_insertions.item_id%type;
9584     tempOrderType ame_temp_insertions.order_type%type;
9585     begin
9586       /*
9587         This procedure generally must populate the following ame_util.approverRecord2 fields,
9588         for each inserted approver:
9589           orig_system
9590           orig_system_id
9591           display_name
9592           action_type_id
9593           group_or_chain_id
9594           occurrence
9595           source
9596           approval_status
9597           item_class_order_number
9598           item_order_number
9599           sub_list_order_number
9600           action_type_order_number
9601           group_or_chain_order_number
9602           member_order_number
9603         The first three of these fields get populated at the beginning of the outermost loop below.
9604         The other fields get populated just before the actual insertion occurs.  This procedure must
9605         therefore decide how to set the order-number fields.  The procedure attempts to set the
9606         order numbers consistent with the order relation of the insertion, where the order relation
9607         anchors the insertion to the approver preceeding or following the insertion in engStApprovers.
9608         See the comments near specific insertApprover calls below.
9609       */
9610       engStApproversCount := engStApprovers.count;
9611       for i in 1 .. engInsertedApproverList.count loop
9612         if(engInsertedApproverList(i).authority <> ame_util.authorityApprover or
9613            engInsertedApproverList(i).api_insertion = ame_util.apiInsertion) then
9614           ame_approver_type_pkg.getOrigSystemIdAndDisplayName(nameIn => engInsertedApproverList(i).name,
9615                                                               origSystemOut => engInsertedApproverList(i).orig_system,
9616                                                               origSystemIdOut => engInsertedApproverList(i).orig_system_id,
9617                                                               displayNameOut => engInsertedApproverList(i).display_name);
9618           parameterFields.delete;
9619           parseFields(stringIn => engInsertionParameterList(i),
9620                       fieldsOut => parameterFields);
9621           /* absoluteOrder */
9622           if(engInsertionOrderTypeList(i) = ame_util.absoluteOrder) then
9623             tempIndex := engInsertionParameterList(i);
9624             if(tempIndex > engStApprovers.count + 1) then
9625               tempIndex := engStApprovers.count + 1;
9626             end if;
9627             engInsertedApproverList(i).source := ame_util.otherInsertion;
9628             if(engStApprovers.exists(tempIndex - 1)  and
9629                engStApprovers(tempIndex - 1).authority = engInsertedApproverList(i).authority and
9630                engStApprovers(tempIndex - 1).item_class = engInsertedApproverList(i).item_class and
9631                engStApprovers(tempIndex - 1).item_id = engInsertedApproverList(i).item_id
9632                ) then
9633               /* Group the insertion with the preceeding approver in engStApprovers. */
9634               engInsertedApproverList(i).action_type_id := engStApprovers(tempIndex - 1).action_type_id;
9635               engInsertedApproverList(i).group_or_chain_id := engStApprovers(tempIndex - 1).group_or_chain_id;
9636               engInsertedApproverList(i).occurrence :=
9637                 getHandlerOccurrence(nameIn => engInsertedApproverList(i).name,
9638                                      itemClassIn => engInsertedApproverList(i).item_class,
9639                                      itemIdIn => engInsertedApproverList(i).item_id,
9640                                      actionTypeIdIn => engInsertedApproverList(i).action_type_id,
9641                                      groupOrChainIdIn => engInsertedApproverList(i).group_or_chain_id);
9642               engInsertedApproverList(i).item_class_order_number :=
9643                 engStApprovers(tempIndex - 1).item_class_order_number;
9644               engInsertedApproverList(i).item_order_number := engStApprovers(tempIndex - 1).item_order_number;
9645               engInsertedApproverList(i).sub_list_order_number := engStApprovers(tempIndex - 1).sub_list_order_number;
9646               engInsertedApproverList(i).action_type_order_number :=
9647                 engStApprovers(tempIndex - 1).action_type_order_number;
9648               engInsertedApproverList(i).group_or_chain_order_number :=
9649                 engStApprovers(tempIndex - 1).group_or_chain_order_number;
9650             elsif(engStApprovers.exists(tempIndex)) then
9651               /* Group the insertion with the following approver in engStApprovers. */
9652               engInsertedApproverList(i).authority := engStApprovers(tempIndex).authority;
9653               engInsertedApproverList(i).action_type_id := engStApprovers(tempIndex).action_type_id;
9654               engInsertedApproverList(i).group_or_chain_id := engStApprovers(tempIndex).group_or_chain_id;
9655               engInsertedApproverList(i).occurrence :=
9656                 getHandlerOccurrence(nameIn => engInsertedApproverList(i).name,
9657                                      itemClassIn => engInsertedApproverList(i).item_class,
9658                                      itemIdIn => engInsertedApproverList(i).item_id,
9659                                      actionTypeIdIn => engInsertedApproverList(i).action_type_id,
9660                                      groupOrChainIdIn => engInsertedApproverList(i).group_or_chain_id);
9661               engInsertedApproverList(i).item_class_order_number := engStApprovers(tempIndex).item_class_order_number;
9662               engInsertedApproverList(i).item_order_number := engStApprovers(tempIndex).item_order_number;
9663               engInsertedApproverList(i).sub_list_order_number := engStApprovers(tempIndex).sub_list_order_number;
9664               engInsertedApproverList(i).action_type_order_number := engStApprovers(tempIndex).action_type_order_number;
9665               engInsertedApproverList(i).group_or_chain_order_number :=
9666                 engStApprovers(tempIndex).group_or_chain_order_number;
9667             else
9668               /* engStApprovers must be empty. */
9669               engInsertedApproverList(i).action_type_id := ame_util.nullInsertionActionTypeId;
9670               engInsertedApproverList(i).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
9671               engInsertedApproverList(i).occurrence := 1;
9672               engInsertedApproverList(i).item_class_order_number :=
9673                 getItemClassOrderNumber(itemClassIdIn =>
9674                   getItemClassId(itemClassNameIn => engInsertedApproverList(i).item_class));
9675               engInsertedApproverList(i).item_order_number :=
9676                 getItemOrderNumber(itemClassNameIn => engInsertedApproverList(i).item_class,
9677                                    itemIdIn => engInsertedApproverList(i).item_id);
9678               engInsertedApproverList(i).sub_list_order_number :=
9679                 getSublistOrderNum(itemClassNameIn => ame_util.headerItemClassName,
9680                                    authorityIn => ame_util.postApprover);
9681               engInsertedApproverList(i).action_type_order_number := getNullActionTypeOrderNumber;
9682               engInsertedApproverList(i).group_or_chain_order_number := 1;
9683             end if;
9684             if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
9685               fnd_log.string
9686                 (fnd_log.level_statement
9687                 ,'ame_engine.processAdhocInsertions'
9688                 ,'Adhoc Insertion approver(absolute order) ::: ' || engInsertedApproverList(i).name
9689                 );
9690             end if;
9691             insertApprover(indexIn => tempIndex,
9692                            approverIn => engInsertedApproverList(i),
9693                            adjustMemberOrderNumbersIn => true,
9694                            inserteeIndexIn => i,
9695                            currentInsIndex => i);
9696             populateInsertionIndexes(indexIn => tempIndex
9697                                     ,insertionOrderIn => engInsertionOrderList(i));
9698             engStApproversCount := engStApproversCount + 1;
9699           /* afterApprover, beforeApprover */
9700           elsif(engInsertionOrderTypeList(i) in (ame_util.afterApprover,
9701                                                  ame_util.beforeApprover)) then
9702             tempIndex := 1; /* post-increment */
9703             loop
9704               tempBoolean := false;
9705               /*
9706                 In this loop, tempBoolean indicates whether engStApprovers(tempIndex) matches
9707                 the insertion parameter.
9708               */
9709               if(engStApprovers(tempIndex).name = parameterFields(1) and
9710                  engStApprovers(tempIndex).occurrence = parameterFields(6) and
9711                  engStApprovers(tempIndex).group_or_chain_id = parameterFields(5) and
9712                  engStApprovers(tempIndex).action_type_id = parameterFields(4) and
9713                  engStApprovers(tempIndex).item_id = parameterFields(3) and
9714                  engStApprovers(tempIndex).item_class = parameterFields(2)) then
9715                 tempBoolean := true;
9716                 if(engInsertionOrderTypeList(i) = ame_util.afterApprover) then
9717                   tempIndex2 := tempIndex + 1;
9718                 else
9719                   tempIndex2 := tempIndex;
9720                 end if;
9721                 engInsertedApproverList(i).action_type_id := engStApprovers(tempIndex).action_type_id;
9722                 engInsertedApproverList(i).group_or_chain_id := engStApprovers(tempIndex).group_or_chain_id;
9723                 engInsertedApproverList(i).occurrence :=
9724                   getHandlerOccurrence(nameIn => engInsertedApproverList(i).name,
9725                                        itemClassIn => engInsertedApproverList(i).item_class,
9726                                        itemIdIn => engInsertedApproverList(i).item_id,
9727                                        actionTypeIdIn => engInsertedApproverList(i).action_type_id,
9728                                        groupOrChainIdIn => engInsertedApproverList(i).group_or_chain_id);
9729                 if(engInsertionIsSpecialForwardee(i) = ame_util.booleanTrue) then
9730                   engInsertedApproverList(i).source := ame_util.specialForwardInsertion;
9731                 else
9732                   if(engInsertionOrderTypeList(i) = ame_util.afterApprover and
9733                      engStApprovers(tempIndex).approval_status = ame_util.forwardStatus) then
9734                     engInsertedApproverList(i).source := ame_util.forwardInsertion;
9735                   elsif(engInsertionOrderTypeList(i) = ame_util.afterApprover and
9736                         engStApprovers(tempIndex).approval_status = ame_util.approveAndForwardStatus) then
9737                     engInsertedApproverList(i).source := ame_util.approveAndForwardInsertion;
9738                   else
9739                     engInsertedApproverList(i).source := ame_util.otherInsertion;
9740                   end if;
9741                 end if;
9742                 engInsertedApproverList(i).item_class_order_number := engStApprovers(tempIndex).item_class_order_number;
9743                 engInsertedApproverList(i).item_order_number := engStApprovers(tempIndex).item_order_number;
9744                 engInsertedApproverList(i).sub_list_order_number := engStApprovers(tempIndex).sub_list_order_number;
9745                 engInsertedApproverList(i).action_type_order_number := engStApprovers(tempIndex).action_type_order_number;
9746                 engInsertedApproverList(i).group_or_chain_order_number :=
9747                   engStApprovers(tempIndex).group_or_chain_order_number;
9748                 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
9749                   fnd_log.string
9750                     (fnd_log.level_statement
9751                     ,'ame_engine.processAdhocInsertions'
9752                     ,'Adhoc Insertion approver(after/before approver) ::: ' || engInsertedApproverList(i).name
9753                     );
9754                 end if;
9755                 insertApprover(indexIn => tempIndex2,
9756                                approverIn => engInsertedApproverList(i),
9757                                adjustMemberOrderNumbersIn => true,
9758                                inserteeIndexIn => i,
9759                                currentInsIndex => i);
9760                 populateInsertionIndexes(indexIn => tempIndex2
9761                                         ,insertionOrderIn => engInsertionOrderList(i));
9762                 engStApproversCount := engStApproversCount + 1;
9763               end if;
9764               if(tempBoolean or
9765                  tempIndex = engStApproversCount) then
9766                 exit;
9767               end if;
9768               tempIndex := tempIndex + 1;
9769             end loop;
9770           else /* first/last pre/post approver */
9771             /*
9772               The source, action_type_id, and group_or_chain_id fields are set in
9773               ame_api3.getAvailableInsertions for these order types.
9774             */
9775             if(engStApproversCount = 0) then
9776               /*
9777                 The four first/last pre/post order types can only occur in an empty list if the insertion
9778                 is for the header item.  Treat any other case of these order types as displaced, here.
9779                 In the code blocks below for these four order types, require that engStApproversCount > 0.
9780               */
9781               if(parameterFields(3) = ame_util.headerItemClassName and
9782                  parameterFields(2) = engTransactionId) then
9783                 engInsertedApproverList(i).occurrence := 1;
9784                 engInsertedApproverList(i).item_class_order_number :=
9785                   getItemClassOrderNumber(itemClassIdIn =>
9786                     getItemClassId(itemClassNameIn => ame_util.headerItemClassName));
9787                 engInsertedApproverList(i).item_order_number := 1;
9788                 engInsertedApproverList(i).sub_list_order_number :=
9789                   getSublistOrderNum(itemClassNameIn => ame_util.headerItemClassName,
9790                                      authorityIn => engInsertedApproverList(i).authority);
9791                 engInsertedApproverList(i).action_type_order_number := getNullActionTypeOrderNumber;
9792                 engInsertedApproverList(i).group_or_chain_order_number := 1;
9793                 engInsertedApproverList(i).member_order_number := 1;
9794                 insertApprover(indexIn => 1,
9795                                approverIn => engInsertedApproverList(i),
9796                                adjustMemberOrderNumbersIn => false,
9797                                inserteeIndexIn => i,
9798                                currentInsIndex => i);
9799                 populateInsertionIndexes(indexIn => 1
9800                                         ,insertionOrderIn => engInsertionOrderList(i));
9801                 engStApproversCount := 1;
9802               else /* displaced */
9803                 engInsertedApproverList(i).occurrence := 1;
9804                 engInsertedApproverList(i).item_class_order_number :=
9805                   getItemClassOrderNumber(itemClassIdIn =>
9806                     getItemClassId(itemClassNameIn => engInsertedApproverList(i).item_class));
9807                 engInsertedApproverList(i).item_order_number := 1;
9808                 engInsertedApproverList(i).sub_list_order_number :=
9809                   getSublistOrderNum(itemClassNameIn => engInsertedApproverList(i).item_class,
9810                                      authorityIn => engInsertedApproverList(i).authority);
9811                 engInsertedApproverList(i).action_type_order_number := getNullActionTypeOrderNumber;
9812                 engInsertedApproverList(i).group_or_chain_order_number := 1;
9813                 engInsertedApproverList(i).member_order_number := 1;
9814                 displacedInserteeIndexes(displacedInserteeIndexes.count + 1) := i;
9815               end if;
9816             else
9817               tempIndex := null;
9818               tempAnchorIndex := null;
9819               /* firstPostApprover */
9820               if(engInsertionOrderTypeList(i) = ame_util.firstPostApprover) then
9821                 /*
9822                   Insert at tempIndex if it's non-null, after checking the possible cases.
9823                   Recall that the case where engStApproversCount = 0 is handled at the
9824                   start of the procedure, that the item id is in parameterFields(3), and
9825                   that the item-class ID is in parameterFields(2).  Here are the cases
9826                   requiring insertion (always at j + 1).
9827                   1.  j = 0,
9828                       post-approver for the right item at j + 1 = 1
9829                   2.  j > 0,
9830                       j < engStApproversCount,
9831                       non-post-approver for the right item at j,
9832                       post-approver for the right item at j + 1
9833                   3.  j > 0,
9834                       j < engStApproversCount,
9835                       non-post-approver for the right item at j,
9836                       any approver for the wrong item at j + 1
9837                   4.  j > 0,
9838                       j = engStApproversCount,
9839                       non-post-approver for the right item at j
9840                   5.  j > 0,
9841                       j < engStApproversCount,
9842                       any approver for the wrong item at j,
9843                       post-approver for the right item at j + 1
9844                   Finally, note that the way the code is written, case 4 must be checked
9845                   before cases 2, 3, and 5, to ensure that for these cases,
9846                   j + 1 <= engStApproversCount.
9847                 */
9848                 /* The zero lower limit is intentional. */
9849                 for j in 0 .. engStApproversCount loop
9850                   tempIndex2 := j + 1;
9851                   if(j = 0) then /* case 1 */
9852                     if(engStApprovers(tempIndex2).authority = ame_util.postApprover and
9853                        engStApprovers(tempIndex2).item_id = parameterFields(3) and
9854                        engStApprovers(tempIndex2).item_class = parameterFields(2)) then
9855                       tempIndex := tempIndex2;
9856                       tempAnchorIndex := tempIndex2;
9857                       exit;
9858                     end if;
9859                   else /* j > 0:  cases 2-5 */
9860                     /*
9861                       non-post-approver for the right item at j:  cases 2-4
9862                       Case 4 comes before the others to prevent indexing into a non-existent
9863                       engStApprovers(tempIndex2) when j = engStApproversCount.
9864                     */
9865                     if(engStApprovers(j).authority <> ame_util.postApprover and
9866                        engStApprovers(j).item_id = parameterFields(3) and
9867                        engStApprovers(j).item_class = parameterFields(2)) then
9868                       if(j = engStApproversCount) then /* case 4 */
9869                         tempIndex := tempIndex2;
9870                         exit;
9871                       end if;
9872                       if(engStApprovers(tempIndex2).authority = ame_util.postApprover and
9873                          engStApprovers(tempIndex2).item_id = parameterFields(3) and
9874                          engStApprovers(tempIndex2).item_class = parameterFields(2)) then /* case 2 */
9875                         tempIndex := tempIndex2;
9876                         tempAnchorIndex := tempIndex2;
9877                         exit;
9878                       end if;
9879                       if(engStApprovers(tempIndex2).item_id <> parameterFields(3) or
9880                          engStApprovers(tempIndex2).item_class <> parameterFields(2)) then /* case 3 */
9881                         tempIndex := tempIndex2;
9882                         exit;
9883                       end if;
9884                       if((engStApprovers(j).item_id <> parameterFields(3) or
9885                           engStApprovers(j).item_class <> parameterFields(2)) and
9886                          engStApprovers(tempIndex2).authority = ame_util.postApprover and
9887                          engStApprovers(tempIndex2).item_id = parameterFields(3) and
9888                          engStApprovers(tempIndex2).item_class = parameterFields(2)) then /* case 5 */
9889                         tempIndex := tempIndex2;
9890                         tempAnchorIndex := tempIndex2;
9891                         exit;
9892                       end if;
9893                     end if;
9894                   end if;
9895                 end loop;
9896               /* firstPreApprover */
9897               elsif(engInsertionOrderTypeList(i) = ame_util.firstPreApprover) then
9898                 /*
9899                   Insert at tempIndex if it's non-null, after checking the possible cases.
9900                   Recall that the case where engStApproversCount = 0 is handled at the
9901                   start of the procedure.  Here are the cases requiring insertion (always
9902                   at j).
9903                   1.  j = 1,
9904                       any approver for the right item at j = 1
9905                   2.  j > 1,
9906                       any approver for the wrong item at j - 1,
9907                       any approver for the right item at j
9908                 */
9909                 for j in 1 .. engStApproversCount loop
9910                   if(j = 1) then
9911                     if(engStApprovers(1).item_id = parameterFields(3) and
9912                        engStApprovers(1).item_class = parameterFields(2)) then /* case 1 */
9913                       tempIndex := 1;
9914                       if(engStApprovers(1).authority = ame_util.preApprover) then
9915                         tempAnchorIndex := 1;
9916                       end if;
9917                       exit;
9918                     end if;
9919                   elsif((engStApprovers(j - 1).item_id <> parameterFields(3) or
9920                          engStApprovers(j - 1).item_class <> parameterFields(2)) and
9921                         engStApprovers(j).item_id = parameterFields(3) and
9922                         engStApprovers(j).item_class = parameterFields(2)) then /* case 2 */
9923                     tempIndex := j;
9924                     if(engStApprovers(j).authority = ame_util.preApprover) then
9925                       tempAnchorIndex := j;
9926                     end if;
9927                     exit;
9928                   end if;
9929                 end loop;
9930               /* lastPostApprover */
9931               elsif(engInsertionOrderTypeList(i) = ame_util.lastPostApprover) then
9932                 /*
9933                   Insert at tempIndex if it's non-null, after checking the possible cases.
9934                   Recall that the case where engStApproversCount = 0 is handled at the
9935                   start of the procedure.  Here are the cases requiring insertion (always
9936                   at j + 1).
9937                   1.  j = engStApproversCount,
9938                       any approver for the right item at j
9939                   2.  j < engStApproversCount,
9940                       any approver for right item at j,
9941                       any approver for wrong item at j + 1
9942                 */
9943                 for j in 1 .. engStApproversCount loop
9944                   if(j = engStApproversCount) then
9945                     if(engStApprovers(j).item_id = parameterFields(3) and
9946                        engStApprovers(j).item_class = parameterFields(2)) then
9947                       tempIndex := engStApproversCount + 1;
9948                       if(engStApprovers(j).authority = ame_util.postApprover) then
9949                         tempAnchorIndex := j;
9950                       end if;
9951                       exit;
9952                     end if;
9953                   else
9954                     if(engStApprovers(j).item_id = parameterFields(3) and
9955                        engStApprovers(j).item_class = parameterFields(2) and
9956                        (engStApprovers(j + 1).item_id <> parameterFields(3) or
9957                        engStApprovers(j + 1).item_class <> parameterFields(2))) then
9958                       tempIndex := j + 1;
9959                       if(engStApprovers(j).authority = ame_util.postApprover) then
9960                         tempAnchorIndex := j;
9961                       end if;
9962                       exit;
9963                     end if;
9964                   end if;
9965                 end loop;
9966               /* lastPreApprover */
9967               else /* engInsertionOrderTypeList(i) = ame_util.lastPreApprover */
9968                 /*
9969                   Insert at tempIndex if it's non-null, after checking the possible cases.
9970                   Recall that the case where engStApproversCount = 0 is handled at the
9971                   start of the procedure.  Here are the cases (always inserting at j):
9972                   1.  j = 1,
9973                       non-pre-approver for the right item at 1
9974                   2.  j > 1,
9975                       j <= engStApproversCount,
9976                       the approver at j - 1 is for the right item,
9977                       the approver at j is for the right item,
9978                       the approver at j - 1 is a pre-approver,
9979                       the approver at j is not a pre-approver
9980                   3.  j > 1,
9981                       j <= engStApproversCount,
9982                       any approver at j - 1 for the wrong item,
9983                       the approver at j is for the right item,
9984                       the approver at j is not a pre-approver
9985                 */
9986                 for j in 1 .. engStApproversCount loop
9987                   if(j = 1) then
9988                     if(engStApprovers(1).item_id = parameterFields(3) and
9989                        engStApprovers(1).item_class = parameterFields(2) and
9990                        engStApprovers(1).authority <> ame_util.preApprover) then /* case 1 */
9991                       tempIndex := 1;
9992                       exit;
9993                     end if;
9994                   else
9995                     if(engStApprovers(j).item_id = parameterFields(3) and
9996                        engStApprovers(j).item_class = parameterFields(2) and
9997                        engStApprovers(j).authority <> ame_util.preApprover) then
9998                       if(engStApprovers(j - 1).item_id = parameterFields(3) and
9999                          engStApprovers(j - 1).item_class = parameterFields(2)) then
10000                         if(engStApprovers(j - 1).authority = ame_util.preApprover) then /* case 2 */
10001                           tempIndex := j;
10002                           tempAnchorIndex := j - 1;
10003                           exit;
10004                         end if;
10005                       else /* case 3 */
10006                         tempIndex := j;
10007                         exit;
10008                       end if;
10009                     end if;
10010                   end if;
10011                 end loop;
10012               end if;
10013               /* Set the remaining fields in the insertee's approverRecord2. */
10014               engInsertedApproverList(i).source := ame_util.otherInsertion;
10015               if(tempAnchorIndex is null) then
10016                 engInsertedApproverList(i).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
10017                 /* This code was commented out to fix BUG (4095846)                                 */
10018                 /* Issue 9 in the list of bugs identified during implementation of                  */
10019                 /* asynchronous parallel approver functionality                                     */
10020                 /* engInsertedApproverList(i).action_type_id := ame_util.nullInsertionActionTypeId; */
10021                 engInsertedApproverList(i).occurrence :=
10022                   getHandlerOccurrence(nameIn => engInsertedApproverList(i).name,
10023                                        itemClassIn => engInsertedApproverList(i).item_class,
10024                                        itemIdIn => engInsertedApproverList(i).item_id,
10025                                        actionTypeIdIn => engInsertedApproverList(i).action_type_id,
10026                                        groupOrChainIdIn => engInsertedApproverList(i).group_or_chain_id);
10027                 engInsertedApproverList(i).item_class_order_number :=
10028                   getItemClassOrderNumber(itemClassIdIn =>
10029                     getItemClassId(itemClassNameIn => engInsertedApproverList(i).item_class));
10030                 engInsertedApproverList(i).item_order_number :=
10031                   getItemOrderNumber(itemClassNameIn => engInsertedApproverList(i).item_class,
10032                                                  itemIdIn => engInsertedApproverList(i).item_id);
10033                 /* Code Modified to fix BUG (4095825)                              */
10034                 /* Issue 2 in the list of bugs identified during implementation of */
10035                 /* asynchronous parallel approver functionality                    */
10036                 if engInsertionOrderTypeList(i) = ame_util.firstPreApprover or
10037                         engInsertionOrderTypeList(i) = ame_util.lastPreApprover then
10038                   engInsertedApproverList(i).sub_list_order_number :=
10039                     getSublistOrderNum(itemClassNameIn => engInsertedApproverList(i).item_class,
10040                                        authorityIn => ame_util.preApprover);
10041                 elsif engInsertionOrderTypeList(i) = ame_util.firstPostApprover or
10042                         engInsertionOrderTypeList(i) = ame_util.lastPostApprover then
10043                   engInsertedApproverList(i).sub_list_order_number :=
10044                     getSublistOrderNum(itemClassNameIn => engInsertedApproverList(i).item_class,
10045                                        authorityIn => ame_util.postApprover);
10046                 end if;
10047                 /* Code Modified to fix BUG (4095846)                                                   */
10048                 /* Issue 9 in the list of bugs identified during implementation of                      */
10049                 /* asynchronous parallel approver functionality                                         */
10050                 /* engInsertedApproverList(i).action_type_order_number := getNullActionTypeOrderNumber; */
10051                 engInsertedApproverList(i).action_type_order_number := 1;
10052                 engInsertedApproverList(i).group_or_chain_order_number := 1;
10053               else
10054                 engInsertedApproverList(i).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
10055                 /* Code Modified to fix BUG (4095846)                                              */
10056                 /* Issue 9 in the list of bugs identified during implementation of                 */
10057                 /* asynchronous parallel approver functionality                                    */
10058                 /* engInsertedApproverList(i).action_type_id := ame_util.nullInsertionActionTypeId;*/
10059                 engInsertedApproverList(i).occurrence :=
10060                   getHandlerOccurrence(nameIn => engInsertedApproverList(i).name,
10061                                        itemClassIn => engInsertedApproverList(i).item_class,
10062                                        itemIdIn => engInsertedApproverList(i).item_id,
10063                                        actionTypeIdIn => engInsertedApproverList(i).action_type_id,
10064                                        groupOrChainIdIn => engInsertedApproverList(i).group_or_chain_id);
10065                 engInsertedApproverList(i).item_class_order_number :=
10066                   engStApprovers(tempAnchorIndex).item_class_order_number;
10067                 engInsertedApproverList(i).item_order_number :=
10068                   engStApprovers(tempAnchorIndex).item_order_number;
10069                 engInsertedApproverList(i).sub_list_order_number :=
10070                   engStApprovers(tempAnchorIndex).sub_list_order_number;
10071                 /* Code Modified to fix BUG (4095846)                                   */
10072                 /* Issue 9 in the list of bugs identified during implementation of      */
10073                 /* asynchronous parallel approver functionality                         */
10074                 /*engInsertedApproverList(i).action_type_order_number :=                */
10075                 /*  engStApprovers(tempAnchorIndex).action_type_order_number;           */
10076                 if engInsertionOrderTypeList(i) = ame_util.firstPreApprover or
10077                      engInsertionOrderTypeList(i) = ame_util.firstPostApprover then
10078                   engInsertedApproverList(i).action_type_order_number :=
10079                     engStApprovers(tempAnchorIndex).action_type_order_number - 1;
10080                 elsif engInsertionOrderTypeList(i) = ame_util.lastPreApprover or
10081                      engInsertionOrderTypeList(i) = ame_util.lastPostApprover then
10082                   engInsertedApproverList(i).action_type_order_number :=
10083                     engStApprovers(tempAnchorIndex).action_type_order_number + 1;
10084                 end if;
10085                 engInsertedApproverList(i).group_or_chain_order_number :=
10086                   engStApprovers(tempAnchorIndex).group_or_chain_order_number;
10087               end if;
10088               /* Perform the insertion if the proper position has been located. */
10089               if(tempIndex is null) then
10090                 displacedInserteeIndexes(displacedInserteeIndexes.count + 1) := i;
10091               else
10092                 /* Code Modified to fix BUG (4095846)                                   */
10093                 /* Issue 9 in the list of bugs identified during implementation of      */
10094                 /* asynchronous parallel approver functionality                         */
10095                 if engInsertionOrderTypeList(i) = ame_util.firstPreApprover or
10096                         engInsertionOrderTypeList(i) = ame_util.firstPostApprover then
10097                   engInsertedApproverList(i).action_type_id := -1;
10098                   if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
10099                     fnd_log.string
10100                       (fnd_log.level_statement
10101                       ,'ame_engine.processAdhocInsertions'
10102                       ,'Adhoc Insertion approver(first pre/first post approver) ::: ' || engInsertedApproverList(i).name
10103                       );
10104                   end if;
10105                   insertApprover(indexIn => tempIndex,
10106                                  approverIn => engInsertedApproverList(i),
10107                                  adjustMemberOrderNumbersIn => true,
10108                                  approverLocationIn => ame_util.firstAmongEquals,
10109                                  inserteeIndexIn => i,
10110                                  currentInsIndex => i);
10111                   populateInsertionIndexes(indexIn => tempIndex
10112                                           ,insertionOrderIn => engInsertionOrderList(i));
10113                 elsif engInsertionOrderTypeList(i) = ame_util.lastPreApprover or
10114                         engInsertionOrderTypeList(i) = ame_util.lastPostApprover then
10115                   engInsertedApproverList(i).action_type_id := -2;
10116                   if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
10117                     fnd_log.string
10118                       (fnd_log.level_statement
10119                       ,'ame_engine.processAdhocInsertions'
10120                       ,'Adhoc Insertion approver(last pre/last post approver) ::: ' || engInsertedApproverList(i).name
10121                       );
10122                   end if;
10123                   insertApprover(indexIn => tempIndex,
10124                                  approverIn => engInsertedApproverList(i),
10125                                  adjustMemberOrderNumbersIn => true,
10126                                  approverLocationIn => ame_util.lastAmongEquals,
10127                                  inserteeIndexIn => i,
10128                                  currentInsIndex => i);
10129                   populateInsertionIndexes(indexIn => tempIndex
10130                                           ,insertionOrderIn => engInsertionOrderList(i));
10131                 end if;
10132                 engStApproversCount := engStApproversCount + 1;
10133               end if;
10134             end if;
10135           end if;
10136         end if;
10137       end loop;
10138       /*
10139         Insert any displaced approvers at the end of their items' lists, if possible; and
10140         otherwise at the end of the transaction's list.
10141       */
10142       for i in 1 .. displacedInserteeIndexes.count loop
10143         parameterFields.delete;
10144         parseFields(stringIn => engInsertionParameterList(displacedInserteeIndexes(i)),
10145                     fieldsOut => parameterFields);
10146         /* Set tempBoolean false if displaced approver i is inserted at the end of its item's list. */
10147         tempBoolean := true;
10148         engStApproversCount := engStApprovers.count;
10149         for j in 1 .. engStApproversCount loop
10150           if(engStApprovers(j).item_id = parameterFields(2) and
10151              engStApprovers(j).item_class = parameterFields(3) and
10152              (j = engStApproversCount or
10153               engStApprovers(j + 1).item_id <> parameterFields(2) or
10154               engStApprovers(j + 1).item_class <> parameterFields(3))) then
10155             if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
10156               fnd_log.string
10157                 (fnd_log.level_statement
10158                 ,'ame_engine.processAdhocInsertions'
10159                 ,'Adhoc Insertion approver(displaced) ::: ' || engInsertedApproverList(displacedInserteeIndexes(i)).name
10160                 );
10161             end if;
10162             insertApprover(indexIn => j + 1,
10163                            approverIn => engInsertedApproverList(displacedInserteeIndexes(i)),
10164                            adjustMemberOrderNumbersIn => true,
10165                            inserteeIndexIn => i,
10166                            currentInsIndex => i);
10167             populateInsertionIndexes(indexIn => j + 1
10168                                     ,insertionOrderIn => engInsertionOrderList(displacedInserteeIndexes(i)));
10169             tempBoolean := false;
10170             exit;
10171           end if;
10172         end loop;
10173         if(tempBoolean) then
10174           if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
10175             fnd_log.string
10176               (fnd_log.level_statement
10177               ,'ame_engine.processAdhocInsertions'
10178               ,'Adhoc Insertion approver(displaced) ::: ' || engInsertedApproverList(displacedInserteeIndexes(i)).name
10179               );
10180           end if;
10181           insertApprover(indexIn => engStApproversCount + 1,
10182                          approverIn => engInsertedApproverList(displacedInserteeIndexes(i)),
10183                          adjustMemberOrderNumbersIn => false,
10184                          inserteeIndexIn => i,
10185                          currentInsIndex => i);
10186           populateInsertionIndexes(indexIn => engStApproversCount + 1
10187                                   ,insertionOrderIn => engInsertionOrderList(displacedInserteeIndexes(i)));
10188         end if;
10189         engStApproversCount := engStApproversCount + 1;
10190       end loop;
10191       exception
10192         when others then
10193           ame_util.runtimeException(packageNameIn => 'ame_engine',
10194                                     routineNameIn => 'processAdHocInsertions',
10195                                     exceptionNumberIn => sqlcode,
10196                                     exceptionStringIn => sqlerrm);
10197           raise;
10198     end processAdHocInsertions;
10199   --+
10200   --
10201   --+
10202   procedure getAllProductions(productionsOut out nocopy ame_util2.productionsTable) is
10203     begin
10204       for i in 1 .. engStProductionsTable.count loop
10205         productionsOut(i).variable_name := engStProductionsTable(i).variable_name;
10206         productionsOut(i).variable_value := engStProductionsTable(i).variable_value;
10207         productionsOut(i).item_class := engStProductionsTable(i).item_class;
10208         productionsOut(i).item_id := engStProductionsTable(i).item_id;
10209       end loop;
10210     end getAllProductions;
10211   procedure getProductions(itemClassIn    in  varchar2
10212                           ,itemIdIn       in  varchar2
10213                           ,productionsOut out nocopy ame_util2.productionsTable) is
10214     tempIndex integer;
10215     begin
10216       tempIndex := 1;
10217       for i in 1 .. engStProductionsTable.count loop
10218         if itemClassIn = engStProductionsTable(i).item_class and
10219          itemIdIn    = engStProductionsTable(i).item_id then
10220           productionsOut(tempIndex).variable_name := engStProductionsTable(i).variable_name;
10221           productionsOut(tempIndex).variable_value := engStProductionsTable(i).variable_value;
10222           productionsOut(tempIndex).item_class := engStProductionsTable(i).item_class;
10223           productionsOut(tempIndex).item_id := engStProductionsTable(i).item_id;
10224           tempIndex := tempIndex+1;
10225         end if;
10226       end loop;
10227     end getProductions;
10228   procedure processActionType as
10229     tempIndex integer;
10230     begin
10231       if(engAppRuleTypes(engAppHandlerFirstIndex) = ame_util.productionRuleType) then
10232         /*
10233           Copy item-level productions to the appropriate engStProductionsTable.  Note that we
10234           have to initialize tempIndex as below to account for the possibility of multiple
10235           production action types.
10236         */
10237         tempIndex := engStProductionsTable.count;
10238         for i in engAppHandlerFirstIndex .. engAppHandlerLastIndex loop
10239           tempIndex := tempIndex + 1;
10240           engStProductionsTable(tempIndex).variable_name  := engAppParameters(i);
10241           engStProductionsTable(tempIndex).variable_value := engAppParameterTwos(i);
10242           engStProductionsTable(tempIndex).item_class     := getHandlerItemClassName;
10243           engStProductionsTable(tempIndex).item_id        := getHandlerItemId;
10244           if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
10245             fnd_log.string
10246               (fnd_log.level_statement
10247               ,'ame_engine.processActionType'
10248               ,'Transaction Production ::: ' || engStProductionsTable(tempIndex).variable_name || '/' || engStProductionsTable(tempIndex).variable_value
10249               );
10250           end if;
10251         end loop;
10252       /*
10253         This elsif is necessary to avoid processing production actions of approver-generating rules.
10254         (The engine processes these after constructing the approver list.)
10255       */
10256       elsif(engActionTypeUsages(engAppActionTypeIds(engAppHandlerFirstIndex)) <>
10257             ame_util.productionRuleType) then
10258         /*
10259           Call the handler for action types other than the production-rule action type.
10260           (Per-approver productions get handled later.)
10261         */
10262         if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
10263           fnd_log.string
10264             (fnd_log.level_statement
10265             ,'ame_engine.processActionType'
10266             ,'Processing Action Type ::: ' || engAppActionTypeIds(engAppHandlerFirstIndex)
10267             );
10268         end if;
10269         execute immediate
10270           'begin ' ||
10271           getActionTypePackageName(actionTypeIdIn => engAppActionTypeIds(engAppHandlerFirstIndex)) ||
10272           '.handler; end;';
10273       end if;
10274       if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
10275           fnd_log.string
10276             (fnd_log.level_statement
10277             ,'ame_engine.processActionType'
10278             ,'Completed processing the action Type ::: ' || engAppActionTypeIds(engAppHandlerFirstIndex)
10279             );
10280       end if;
10281       exception
10282         when others then
10283           ame_util.runtimeException(packageNameIn => 'ame_engine',
10284                                     routineNameIn => 'processActionType',
10285                                     exceptionNumberIn => sqlcode,
10286                                     exceptionStringIn => sqlerrm);
10287           raise;
10288     end processActionType;
10289   procedure populateInsertionIndexes(indexIn in integer
10290                                     ,insertionOrderIn in integer) as
10291     firstIndex integer;
10292     lastIndex integer;
10293     tempValue integer;
10294     begin
10295       firstIndex := engStInsertionIndexes.first;
10296       if(engStInsertionIndexes.exists(firstIndex)) then
10297         lastIndex := engStInsertionIndexes.last;
10298         while engStInsertionIndexes.exists(lastIndex) and lastIndex >= indexIn loop
10299           tempValue := engStInsertionIndexes(lastIndex);
10300           engStInsertionIndexes(lastIndex + 1) := tempValue;
10301           engStInsertionIndexes.delete(lastIndex);
10302           lastIndex := engStInsertionIndexes.prior(lastIndex + 1);
10303         end loop;
10304         engStInsertionIndexes(indexIn) := insertionOrderIn;
10305       else
10306         engStInsertionIndexes(indexIn) := insertionOrderIn;
10307       end if;
10308     end populateInsertionIndexes;
10309   procedure processSuppressDeviation(approverIndexIn in number,suppressApproverIndex in number) as
10310    tempcount number;
10311   begin
10312    engDeviationResultList(approverIndexIn).effectiveDate := engSuppressionDateList(suppressApproverIndex);
10313    engDeviationResultList(approverIndexIn).reason := engSupperssionReasonList(suppressApproverIndex);
10314    exception
10315      when others then
10316        ame_util.runtimeException(packageNameIn => 'ame_engine',
10317                                  routineNameIn => 'processSuppressDeviation',
10318                                  exceptionNumberIn => sqlcode,
10319                                  exceptionStringIn => sqlerrm);
10320   end processSuppressDeviation;
10321   procedure processSuppressions as
10322     begin
10323       for i in 1 .. engDeletedApproverList.count loop
10324         for j in 1 .. engStApprovers.count loop
10325           if(engStApprovers(j).name = engDeletedApproverList(i).name and
10326              engStApprovers(j).occurrence = engDeletedApproverList(i).occurrence and
10327              engStApprovers(j).group_or_chain_id = engDeletedApproverList(i).group_or_chain_id and
10328              engStApprovers(j).action_type_id = engDeletedApproverList(i).action_type_id and
10329              engStApprovers(j).item_id = engDeletedApproverList(i).item_id and
10330              engStApprovers(j).item_class = engDeletedApproverList(i).item_class) then
10331             engStApprovers(j).approval_status := ame_util.suppressedStatus;
10332             engStApprovers(j).source := ame_util.apiSuppression;
10333             processSuppressDeviation(j,i);
10334             if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
10335               fnd_log.string
10336                 (fnd_log.level_statement
10337                 ,'ame_engine.processSuppressions'
10338                 ,'Suppressed approver ::: ' || engStApprovers(j).name
10339                 );
10340             end if;
10341           end if;
10342         end loop;
10343       end loop;
10344       exception
10345         when others then
10346           ame_util.runtimeException(packageNameIn => 'ame_engine',
10347                                     routineNameIn => 'processSuppressions',
10348                                     exceptionNumberIn => sqlcode,
10349                                     exceptionStringIn => sqlerrm);
10350           raise;
10351    end processSuppressions;
10352   procedure processExceptions as
10353     authorityRuleSuppressed boolean;
10354     currentFirstAuthorityIndex integer;
10355     currentFirstExceptionIndex integer;
10356     currentFirstItemIndex integer;
10357     currentLastAuthorityIndex integer;
10358     currentLastExceptionIndex integer;
10359     currentLastItemIndex integer;
10360     currentItemClassId integer;
10361     currentItemId ame_util.stringType;
10362     ruleCount integer;
10363     tempAttributeId integer;
10364     tempAttributeIdsToMatch ame_util.idList;
10365     tempExcOrdCondAttributeIds ame_util.idList;
10366     tempBoolean boolean;
10367     tempBoolean2 boolean;
10368     begin
10369       /* Handle the empty-rule-list case first. */
10370       if(engAppRuleIds.count = 0) then
10371         return;
10372       end if;
10373       authorityRuleSuppressed := false;
10374       /* Check for exception rules. */
10375       ruleCount := engAppRuleIds.count; /* This value gets used later in the code too. */
10376       tempBoolean := true;
10377       for i in 1 .. ruleCount loop
10378         if(engAppRuleTypes(i) = ame_util.exceptionRuleType) then
10379           tempBoolean := false;
10380           exit;
10381         end if;
10382       end loop;
10383       if(tempBoolean) then /* No exception rules. */
10384         return;
10385       end if;
10386       /* Now handle the case of a nonempty rule list containing at least one exception rule. */
10387       currentLastItemIndex := 0; /* This will set currentFirstItemIndex to one below. */
10388       loop /* Loop through the sublists of rules applying to an item. */
10389         /* Initialize the current[whatever]Index values. */
10390         currentFirstItemIndex := currentLastItemIndex + 1;
10391         currentLastItemIndex := null;
10392         currentFirstAuthorityIndex := null;
10393         currentLastAuthorityIndex := null;
10394         currentFirstExceptionIndex := null;
10395         currentLastExceptionIndex := null;
10396         currentItemClassId := engAppRuleItemClassIds(currentFirstItemIndex);
10397         currentItemId := engAppAppItemIds(currentFirstItemIndex);
10398         /* Set the current[whatever]Index values. */
10399         for i in currentFirstItemIndex .. ruleCount loop
10400           if(currentItemClassId <> engAppRuleItemClassIds(i) or
10401              currentItemId <> engAppAppItemIds(i)) then
10402             currentLastItemIndex := i - 1;
10403             exit;
10404           elsif(i = ruleCount) then
10405             currentLastItemIndex := i;
10406           end if;
10407           if(engAppRuleTypes(i) = ame_util.authorityRuleType) then
10408             if(currentFirstAuthorityIndex is null) then
10409               currentFirstAuthorityIndex := i;
10410             end if;
10411             currentLastAuthorityIndex := i;
10412           elsif(engAppRuleTypes(i) = ame_util.exceptionRuleType) then
10413             if(currentFirstExceptionIndex is null) then
10414               currentFirstExceptionIndex := i;
10415             end if;
10416             currentLastExceptionIndex := i;
10417           end if;
10418         end loop;
10419         /* Process the current item's exception rules (if any). */
10420         if(currentFirstExceptionIndex is not null) then
10421           for i in currentFirstExceptionIndex .. currentLastExceptionIndex loop
10422             /*
10423               Build the list of attribute IDs for the ordinary conditions used by this exception
10424               (in the local variable tempExcOrdCondAttributeIds) by looping through the engACU variables
10425               until the current exception's rule ID is matched.  Index the list of attribute IDs by
10426               attribute ID (the value doesn't matter, so we set it to a constant--one--for efficiency).
10427               Here tempBoolean indicates whether the exception rule has been found in the engACU
10428               variables, so we can exit the inner loop once we find all of the exception's attributes.
10429             */
10430             tempBoolean := false;
10431             tempExcOrdCondAttributeIds.delete;
10432             for j in 1 .. engACUsageRuleIds.count loop
10433               if(engACUsageRuleIds(j) = engAppRuleIds(i)) then
10434                 tempBoolean := true;
10435                 if(engACConditionTypes(engACUsageConditionIds(j)) = ame_util.ordinaryConditionType) then
10436                   tempExcOrdCondAttributeIds(engACAttributeIds(engACUsageConditionIds(j))) := 1;
10437                 end if;
10438               elsif(tempBoolean) then
10439                 exit;
10440               end if;
10441             end loop;
10442             /* Suppress authority rules as necessary. */
10443             if(currentFirstAuthorityIndex is not null) then
10444               for j in currentFirstAuthorityIndex .. currentLastAuthorityIndex loop
10445                 /* A previous iteration of the i loop could have suppressed the rule at j; check for this. */
10446                 if(engAppRuleIds.exists(j)) then
10447                   /*
10448                     Rather than rebuild tempExcOrdCondAttributeIds at each iteration,
10449                     copy it at each iteration, so we can freely delete entries in the
10450                     copy.
10451                   */
10452                   tempAttributeIdsToMatch.delete;
10453                   ame_util.copyIdList(idListIn => tempExcOrdCondAttributeIds,
10454                                       idListOut => tempAttributeIdsToMatch);
10455                   /*
10456                     For an applicable exception to override an otherwise applicable authority rule,
10457                     both rules' ordinary conditions must be defined on the same attributes.  (If
10458                     neither rule has any ordinary conditions, the exception overrides the authority
10459                     rule.)  Here tempBoolean indicates whether each of the authority rule's
10460                     attributes were matched, and tempBoolean2 indicates whether the target authority
10461                     rule has been found in the engACU variables.
10462                   */
10463                   tempBoolean := true;
10464                   tempBoolean2 := false;
10465                   for k in 1 .. engACUsageRuleIds.count loop
10466                     if(engACUsageRuleIds(k) = engAppRuleIds(j)) then
10467                       tempBoolean2 := true;
10468                       /*
10469                         (An authority rule only has ordinary conditions, so we don't have to check
10470                         the condition type here.)
10471                       */
10472                       tempAttributeId := engACAttributeIds(engACUsageConditionIds(k));
10473                       if(tempAttributeIdsToMatch.exists(tempAttributeId)) then
10474                         tempAttributeIdsToMatch.delete(tempAttributeId);
10475                       else
10476                         tempBoolean := false;
10477                         exit;
10478                       end if;
10479                     elsif(tempBoolean2) then
10480                       exit;
10481                     end if;
10482                   end loop;
10483                   if(tempBoolean and
10484                      tempAttributeIdsToMatch.count = 0) then
10485                     /*
10486                       All of the authority rule's conditions' attributes were matched, and all of the
10487                       exception's ordinary conditions' attributes were matched; so, delete the authority
10488                       rule from the list of applicable rules.
10489                     */
10490                     authorityRuleSuppressed := true;
10491                     engAppItemClassIds.delete(j);
10492                     engAppItemIds.delete(j);
10493                     engAppRuleIds.delete(j);
10494                     engRuleAppliedYN.delete(j);
10495                     engAppRuleTypes.delete(j);
10496                     engAppActionTypeIds.delete(j);
10497                     engAppParameters.delete(j);
10498                     engAppParameterTwos.delete(j);
10499                     engAppRuleItemClassIds.delete(j);
10500                     engAppAppItemIds.delete(j);
10501                   end if;
10502                 end if;
10503               end loop; /* j */
10504             end if;
10505             /*
10506               Convert the exception rule to an authority rule, so it gets processed with
10507               the remaining authority rules.
10508             */
10509             engAppRuleTypes(i) := ame_util.authorityRuleType;
10510           end loop;
10511         end if;
10512         /* Exit the outer loop if no more item rule lists exist. */
10513         if(currentLastItemIndex = ruleCount) then
10514           exit;
10515         end if;
10516       end loop;
10517       /* Re-compact the engApp lists if any authority rules got deleted. */
10518       if(authorityRuleSuppressed) then
10519         compactEngAppLists(compactPrioritiesIn => false,
10520                            compactActionTypeIdsIn => true,
10521                            compactParametersIn => true);
10522       end if;
10523       exception
10524         when others then
10525           ame_util.runtimeException(packageNameIn => 'ame_engine',
10526                                     routineNameIn => 'processExceptions',
10527                                     exceptionNumberIn => sqlcode,
10528                                     exceptionStringIn => sqlerrm);
10529           raise;
10530     end processExceptions;
10531   procedure processRepeatedApprovers as
10532     engAppRuleIdsCount integer;
10533     engStApproversCount integer;
10534     productionActionTypeId integer;
10535     repeatedApproversMode ame_util.attributeValueType;
10536     repeatedByApproverIndex integer;
10537     repeatedIndexesList ame_util.idList;
10538     tempAuthority ame_util.charType;
10539     tempActionTypeId integer;
10540     tempCount integer;
10541     tempEngStItemIndex integer;
10542     tempEngStProductionIndex integer;
10543     tempEngStRuleIndex integer;
10544     tempFirstIndexOfLastItem integer;
10545     tempFirstOccurrenceCurGrouping integer;
10546     tempGroupOrChainId integer;
10547     tempItemClass ame_util.stringType;
10548     tempItemId ame_util.stringType;
10549     tempApproverCategory ame_util.charType;
10550     tempProcessApprover boolean;
10551     tempRuleNotFound boolean;
10552     tempRuleIdList ame_util.idList;
10553     tempRuleIdList2 ame_util.idList;
10554     tempSourceDescription ame_util.longStringType;
10555     treeLevel integer;
10556     tempRepeatedAprCount number;
10557     tempChangeStatus boolean;
10558     begin
10559       /*
10560         This procedure does two things:  (1) suppress repeated approvers, and (2) aggregate various
10561         approver-related data in appropriate engSt package variables.  The aggregation has to occur
10562         for all occurrences of a wf_roles.name value in engStApprovers, at once; so this procedure's
10563         outer loop iterates through engStApprovers, doing the aggregation.  The inner loop suppresses
10564         repeated approvers.
10565       */
10566       tempEngStItemIndex := 0; /* pre-increment */
10567       tempEngStProductionIndex := 0; /* pre-increment */
10568       tempEngStRuleIndex := 0; /* pre-increment */
10569       repeatedApproversMode := getConfigVarValue(configVarNameIn => ame_util.repeatedApproverConfigVar);
10570       /* Set treeLevel for efficiency in the inner loop. */
10571       if(repeatedApproversMode = ame_util.oncePerTransaction) then
10572         treeLevel := 0;
10573       elsif(repeatedApproversMode = ame_util.oncePerItemClass) then
10574         treeLevel := 1;
10575       elsif(repeatedApproversMode = ame_util.oncePerItem) then
10576         treeLevel := 2;
10577       elsif(repeatedApproversMode = ame_util.oncePerSublist) then
10578         treeLevel := 3;
10579       elsif(repeatedApproversMode = ame_util.oncePerActionType) then
10580         treeLevel := 4;
10581       elsif(repeatedApproversMode = ame_util.oncePerGroupOrChain) then
10582         treeLevel := 5;
10583       else /* repeatedApproversMode = ame_util.eachOccurrence */
10584         treeLevel := 6;
10585       end if;
10586       engStApproversCount := engStApprovers.count;
10587       for i in 1 .. engStApproversCount loop
10588         /*
10589           We only want to process an approver if the approver has not been previously processed and
10590           has not been suppressed.  If an approver was suppressed, they can't aggregate the approvals
10591           requirements of subsequent occurrences of the same wf_roles.name in engStApprovers.  If an
10592           approver was previously processed, we don't want to duplicate their data in the engStItem
10593           variables.
10594         */
10595         tempProcessApprover := true;
10596         if(engStApprovers(i).approval_status in (ame_util.suppressedStatus
10597                                                 ,ame_util.repeatedStatus
10598                                                 ,ame_util.beatByFirstResponderStatus)) then
10599           tempProcessApprover := false;
10600         else
10601           for j in 1 .. (i - 1) loop
10602             if(engStApprovers(j).name = engStApprovers(i).name and
10603                engStApprovers(j).approver_category = engStApprovers(i).approver_category) then
10604               tempProcessApprover := false;
10605               exit;
10606             end if;
10607           end loop;
10608         end if;
10609         if(tempProcessApprover) then
10610           /*
10611             Iterate through the rest of the approver list, looking for engStApprovers(i).name, and outputting
10612             each occurrence's data as required to various engSt variables.  If engStApprovers(i).name has
10613             already occurred in the current grouping, set engStApprovers(i).approval_status to
10614             ame_util.repeatedStatus and output its data for the index tempFirstOccurrenceCurGrouping.
10615             Otherwise output its data for index j.  (Set tempFirstOccurrenceCurGrouping to j when we find a
10616             new repeated-approvers grouping.)
10617           */
10618           for j in i .. engStApproversCount loop
10619             if(engStApprovers(j).name = engStApprovers(i).name and
10620                engStApprovers(j).approver_category = engStApprovers(i).approver_category) then
10621               /*
10622                  If repeatedApproversMode is ame_util.oncePerTransaction (that is, treeLevel = 6),
10623                  all occurrences of the approver with j > i are repeated.
10624               */
10625               if(j = i or
10626                  treeLevel = 6 or
10627                  (treelevel = 5 and tempGroupOrChainId <> engStApprovers(j).group_or_chain_id) or
10628                  (treeLevel > 3 and tempActionTypeId <> engStApprovers(j).action_type_id) or
10629                  (treeLevel > 2 and tempAuthority <> engStApprovers(j).authority) or
10630                  (treeLevel > 1 and tempItemId <> engStApprovers(j).item_id) or
10631                  (treeLevel > 0 and tempItemClass <> engStApprovers(j).item_class)) then
10632                 /* We're in a new repeatedApprovers grouping. */
10633                 tempFirstOccurrenceCurGrouping := j;
10634                 tempGroupOrChainId := engStApprovers(j).group_or_chain_id;
10635                 tempActionTypeId := engStApprovers(j).action_type_id;
10636                 tempAuthority := engStApprovers(j).authority;
10637                 tempItemId := engStApprovers(j).item_id;
10638                 tempItemClass := engStApprovers(j).item_class;
10639                 repeatedIndexesList(1) := j;
10640               else /* This is a repeated approver. */
10641                 /*
10642                   Don't overwrite non-null statuses with ame_util.repeatedStatus.  These can reflect
10643                   per-item approver responses.  See the ame_api2.updateApprovalStatus code for details.
10644                   Also, don't suppress special forwardees.  See bug 3401298 for details.
10645                 */
10646                 if(engStApprovers(j).approval_status is null and
10647                    engStApprovers(j).source not like ame_util.specialForwardInsertion || '%') then
10648                   engStApprovers(j).approval_status := ame_util.repeatedStatus;
10649                   if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
10650                     fnd_log.string
10651                       (fnd_log.level_statement
10652                       ,'ame_engine.processRepeatedApprovers'
10653                       ,'Repeated Approver ::: ' || engStApprovers(j).name
10654                       );
10655                   end if;
10656                 end if;
10657                 if engStApprovers(j).approval_status in (ame_util.repeatedStatus
10658                                                         ,ame_util.notifiedByRepeatedStatus
10659                                                         ,ame_util.approvedByRepeatedStatus
10660                                                         ,ame_util.rejectedByRepeatedStatus
10661                                                         ,ame_util.rejectStatus
10662                                                         ,ame_util.approvedStatus
10663                                                         ,ame_util.notifiedStatus) then
10664                   /* Get the repeated by approver's tree node index */
10665                   repeatedIndexesList(repeatedIndexesList.count + 1) := j;
10666                 end if;
10667               end if;
10668             end if;
10669           end loop;
10670           tempCount := engStRepeatedIndexes.count;
10671           if repeatedIndexesList.count > 1 then
10672             for x in 1 .. repeatedIndexesList.count loop
10673               for y in 1 .. repeatedIndexesList.count loop
10674                 tempCount := tempCount + 1;
10675                 engStRepeatedIndexes(tempCount) := repeatedIndexesList(x);
10676                 engStRepeatedAppIndexes(tempCount) := repeatedIndexesList(y);
10677               end loop;
10678             end loop;
10679           end if;
10680           repeatedIndexesList.delete;
10681         end if;
10682       end loop;
10683       -- Handle the case of migration from pre ASP to ASP.
10684       for i in 1 .. engStApprovers.count loop
10685         for j in 1 .. engStRepeatedIndexes.count loop
10686           if engStRepeatedIndexes(j) = i and engStRepeatedAppIndexes(j) <> i then
10687             if engStApprovers(i).approval_status = ame_util.repeatedStatus or
10688                engStApprovers(i).approval_status is null then
10689               if engStApprovers(engStRepeatedAppIndexes(j)).approval_status = ame_util.approvedStatus then
10690                 engStApprovers(i).approval_status := ame_util.approvedByRepeatedStatus;
10691               elsif engStApprovers(engStRepeatedAppIndexes(j)).approval_status
10692                                               = ame_util.noResponseStatus then
10693                 engStApprovers(i).approval_status := ame_util2.noResponseByRepeatedStatus;
10694               elsif engStApprovers(engStRepeatedAppIndexes(j)).approval_status
10695                                               = ame_util.notifiedStatus then
10696                 engStApprovers(i).approval_status := ame_util.notifiedByRepeatedStatus;
10697               elsif engStApprovers(engStRepeatedAppIndexes(j)).approval_status
10698                                               = ame_util.forwardStatus then
10699                 engStApprovers(i).approval_status := ame_util2.forwardByRepeatedStatus;
10700               end if;
10701             end if;
10702           end if;
10703         end loop;
10704       end loop;
10705       -- handle the repetaed status case
10706       tempRepeatedAprCount := engStRepeatedIndexes.count;
10707       for i in 1..engStApprovers.count loop
10708         if engStApprovers(i).approval_status in (ame_util.notifiedByRepeatedStatus
10709                                                 ) then
10710           if tempRepeatedAprCount = 0 then
10711             if engStApprovers(i).approval_status = ame_util.notifiedByRepeatedStatus then
10712               engStApprovers(i).approval_status := ame_util.notifiedStatus ;
10713             end if;
10714           end if;
10715           tempChangeStatus := true;
10716           for j in 1..tempRepeatedAprCount loop
10717             if engStRepeatedIndexes(j) = i and engStRepeatedAppIndexes(j) <> i then
10718               if engStApprovers(engStRepeatedAppIndexes(j)).approval_status is null or
10719                  (engStApprovers(engStRepeatedAppIndexes(j)).approval_status = ame_util.notifiedStatus
10720                    and engStApprovers(i).approval_status = ame_util.notifiedByRepeatedStatus ) then
10721                  tempChangeStatus := false;
10722                 exit;
10723               end if;
10724             end if;
10725           end loop;
10726           if tempChangeStatus then
10727             if engStApprovers(i).approval_status = ame_util.notifiedByRepeatedStatus then
10728               engStApprovers(i).approval_status := ame_util.notifiedStatus ;
10729             end if;
10730           end if;
10731         end if;
10732       end loop;
10733       exception
10734         when others then
10735           ame_util.runtimeException(packageNameIn => 'ame_engine',
10736                                     routineNameIn => 'processRepeatedApprovers',
10737                                     exceptionNumberIn => sqlcode,
10738                                     exceptionStringIn => sqlerrm);
10739           raise;
10740     end processRepeatedApprovers;
10741   procedure processRules(processOnlyProductionsIn in boolean default false) as
10742     currentActionTypeId integer;
10743     currentFirstItemIndex integer;
10744     currentFirstRuleIndexes ame_util.idList; /* indexed by rule type */
10745     currentIndex integer;
10746     currentItemClassId integer;
10747     currentItemId ame_util.stringType;
10748     currentLastItemIndex integer;
10749     currentLastRuleIndexes ame_util.idList; /* indexed by rule type */
10750     currentRuleType integer;
10751     ruleCount integer;
10752     ruleTypes ame_util.idList;
10753     tempIndex integer;
10754     tempLastRuleIndex integer;
10755     tempRuleType integer;
10756     ruleTypeUpperLimit integer;
10757     begin
10758       /* Handle the empty-rule-list case first. */
10759       if(engAppRuleIds.count = 0) then
10760         return;
10761       end if;
10762       /* Now handle the nonempty-rule-list case. . . . */
10763       /*
10764         Set the order in which rule types are processed, for a given item.
10765         Combination rules have already been split into their single-action
10766         components, and exceptions have been converted into authority rules,
10767         so ignore these rule types.
10768       */
10769       ruleTypes(1) := ame_util.productionRuleType;
10770       ruleTypes(2) := ame_util.preListGroupRuleType;
10771       ruleTypes(3) := ame_util.authorityRuleType;
10772       ruleTypes(4) := ame_util.postListGroupRuleType;
10773       ruleTypes(5) := ame_util.listModRuleType;
10774       ruleTypes(6) := ame_util.substitutionRuleType;
10775       /* Initialize the engine substitution variables. */
10776       engAppSubHandlerFirstIndex  := null;
10777       engAppSubHandlerLastIndex  := null;
10778       /* Initialize the state variables. */
10779       ruleCount := engAppRuleIds.count;
10780       currentItemClassId := engAppRuleItemClassIds(1);
10781       currentItemId := engAppAppItemIds(1);
10782       currentRuleType := engAppRuleTypes(1);
10783       currentFirstItemIndex := 1;
10784       currentFirstRuleIndexes(currentRuleType) := 1;
10785       currentIndex := 2;
10786       /* Iterate through the items. */
10787       loop
10788         if(currentIndex > ruleCount or
10789            currentItemClassId <> engAppRuleItemClassIds(currentIndex) or
10790            currentItemId <> engAppAppItemIds(currentIndex)) then
10791           currentLastItemIndex := currentIndex - 1;
10792           currentLastRuleIndexes(currentRuleType) := currentLastItemIndex;
10793         elsif(currentRuleType <> engAppRuleTypes(currentIndex)) then
10794           currentLastRuleIndexes(currentRuleType) := currentIndex - 1;
10795           currentRuleType := engAppRuleTypes(currentIndex);
10796           currentFirstRuleIndexes(currentRuleType) := currentIndex;
10797         end if;
10798         if(currentLastItemIndex is not null) then
10799           /* Process the current item's rules. */
10800           if processOnlyProductionsIn then
10801             if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
10802               fnd_log.string
10803                 (fnd_log.level_statement
10804                 ,'ame_engine.processRules'
10805                 ,'Processing only production rules'
10806                 );
10807             end if;
10808             ruleTypeUpperLimit := 1;
10809           else
10810             if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
10811               fnd_log.string
10812                 (fnd_log.level_statement
10813                 ,'ame_engine.processRules'
10814                 ,'Processing all rules'
10815                 );
10816             end if;
10817             ruleTypeUpperLimit := 6;
10818           end if;
10819           for i in 1 .. ruleTypeUpperLimit loop
10820             /* Process the action types within rule type ruleTypes(i). */
10821             tempRuleType := ruleTypes(i);
10822             if(currentFirstRuleIndexes.exists(tempRuleType)) then
10823               /* Initialize the action-type state variables. */
10824               engAppHandlerFirstIndex := currentFirstRuleIndexes(tempRuleType);
10825               currentActionTypeId := engAppActionTypeIds(engAppHandlerFirstIndex);
10826               tempIndex := engAppHandlerFirstIndex + 1;
10827               tempLastRuleIndex := currentLastRuleIndexes(tempRuleType);
10828               loop
10829                 if(tempIndex > tempLastRuleIndex or
10830                    currentActionTypeId <> engAppActionTypeIds(tempIndex)) then
10831                   /* Process the current action type for the current item. */
10832                   engAppHandlerLastIndex := tempIndex - 1;
10833                   processActionType;
10834                   if (currentRuleType = ame_util.substitutionRuleType) then
10835                     /* Set variables so subsequent call to the substitution handler is
10836                     possible without iterating through the applicable rule list again */
10837                     engAppSubHandlerFirstIndex :=currentFirstRuleIndexes(tempRuleType);
10838                     engAppSubHandlerLastIndex := currentLastRuleIndexes(tempRuleType);
10839                   end if;
10840                   if(tempIndex <= tempLastRuleIndex) then
10841                     /* Update the current action-type state variables. */
10842                     engAppHandlerFirstIndex := tempIndex;
10843                     currentActionTypeId := engAppActionTypeIds(tempIndex);
10844                   end if;
10845                 end if;
10846                 /* Iterate or exit. */
10847                 if(tempIndex > tempLastRuleIndex) then
10848                   exit;
10849                 end if;
10850                 tempIndex := tempIndex + 1;
10851               end loop;
10852             end if;
10853           end loop;
10854           if(currentIndex <= ruleCount) then
10855             /* Update the current state variables. */
10856             currentFirstRuleIndexes.delete;
10857             currentLastRuleIndexes.delete;
10858             currentItemClassId := engAppRuleItemClassIds(currentIndex);
10859             currentItemId := engAppAppItemIds(currentIndex);
10860             currentRuleType := engAppRuleTypes(currentIndex);
10861             currentFirstItemIndex := currentIndex;
10862             currentFirstRuleIndexes(currentRuleType) := currentIndex;
10863             currentLastItemIndex := null;
10864           end if;
10865         end if;
10866         /* Iterate or exit. */
10867         if(currentIndex > ruleCount) then
10868           exit;
10869         end if;
10870         currentIndex := currentIndex + 1;
10871       end loop;
10872       if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
10873         if engStApprovers.count = 0 then
10874           fnd_log.string
10875             (fnd_log.level_statement
10876             ,'ame_engine.processRules'
10877             ,'**************** No Approvers ******************'
10878             );
10879         else
10880           for i in 1 .. engStApprovers.count loop
10881             fnd_log.string
10882               (fnd_log.level_statement
10883               ,'ame_engine.processRules'
10884               ,'Approver ::: ' || engStApprovers(i).name
10885               );
10886           end loop;
10887         end if;
10888       end if;
10889       exception
10890         when others then
10891           ame_util.runtimeException(packageNameIn => 'ame_engine',
10892                                     routineNameIn => 'processRules',
10893                                     exceptionNumberIn => sqlcode,
10894                                     exceptionStringIn => sqlerrm);
10895           raise;
10896     end processRules;
10897   procedure processRelativePriorities as
10898     currentItemClassId integer;
10899     currentItemId ame_util.stringType;
10900     currentRuleType integer;
10901     currentThreshold integer;
10902     engAppRuleIdsCount integer;
10903     ruleDeleted boolean;
10904     tempAbsoluteThreshold integer;
10905     tempDoRelativePriorities boolean;
10906     tempFirstIndex integer;
10907     tempLastIndex integer;
10908     tempThresholdCounter integer;
10909     tempThresholds ame_util.idList;
10910     ruleExists boolean;
10911     tempIndex integer;
10912     oldTempIndex integer;
10913     begin
10914       /* Handle the trivial case here, so we can assume a non-empty applicable-rules list. */
10915       if(engAppRuleIds.count = 0) then
10916         return;
10917       end if;
10918       /* Now for the non-empty-list case. */
10919       ruleDeleted := false;
10920       /* Now for the non-empty-list case. */
10921       if engEvalPrioritiesPerItem then
10922         /* Evaluate priorites per item */
10923         tempFirstIndex := 1;
10924         engAppRuleIdsCount := engAppRuleIds.count;
10925         loop
10926           currentItemClassId := engAppRuleItemClassIds(tempFirstIndex);
10927           currentItemId := engAppAppItemIds(tempFirstIndex);
10928           currentRuleType := engAppRuleTypes(tempFirstIndex);
10929           tempThresholds.delete;
10930           tempLastIndex := null;
10931           tempDoRelativePriorities := engPriorityModes(currentRuleType) = ame_util.relativeRulePriority;
10932           /* Find tempLastIndex and optionally set the values in tempThresholds. */
10933           for i in tempFirstIndex .. engAppRuleIdsCount loop
10934             /* The following if does its comparisons in descending order of probability of success, for efficiency. */
10935             if(currentRuleType <> engAppRuleTypes(i) or
10936                currentItemId <> engAppAppItemIds(i) or
10937                currentItemClassId <> engAppRuleItemClassIds(i)) then
10938               tempLastIndex := i - 1;
10939               exit;
10940             else
10941               if(tempDoRelativePriorities) then
10942                 /* The tempThresholds index and value are the same for convenience. */
10943                 if engAppPriorities(i) is null then
10944                   tempThresholds(99999) := engAppPriorities(i);
10945                 else
10946                   tempThresholds(engAppPriorities(i)) := engAppPriorities(i);
10947                 end if;
10948               end if;
10949             end if;
10950           end loop;
10951           if(tempLastIndex is null) then
10952             tempLastIndex := engAppRuleIdsCount;
10953           end if;
10954           if(tempDoRelativePriorities) then
10955             /* Find the absolute threshold equivalent to the relative. */
10956             tempAbsoluteThreshold := tempThresholds.first;
10957             tempThresholdCounter := 1;
10958             currentThreshold := engPriorityThresholds(currentRuleType);
10959             while (tempThresholdCounter < currentThreshold) loop
10960               tempAbsoluteThreshold := tempThresholds.next(tempAbsoluteThreshold);
10961               tempThresholdCounter := tempThresholdCounter + 1;
10962             end loop;
10963             /* Do priority processing between tempFirstIndex and tempLastIndex. */
10964             for i in tempFirstIndex .. tempLastIndex loop
10965               if(engAppPriorities(i) is null or
10966                  engAppPriorities(i) > tempAbsoluteThreshold) then
10967                 engAppRuleIds.delete(i);
10968                 engRuleAppliedYN.delete(i);
10969                 engAppItemClassIds.delete(i);
10970                 engAppItemIds.delete(i);
10971                 engAppPriorities.delete(i);
10972                 engAppApproverCategories.delete(i);
10973                 engAppRuleTypes.delete(i);
10974                 engAppRuleItemClassIds.delete(i);
10975                 engAppAppItemIds.delete(i);
10976                 ruleDeleted := true;
10977               end if;
10978             end loop;
10979           end if;
10980           /* If there are no more applicable rules to process, stop. */
10981           if(tempLastIndex = engAppRuleIdsCount) then
10982             exit;
10983           end if;
10984           tempFirstIndex := tempLastIndex + 1;
10985         end loop;
10986       else
10987         /* Evaluate priorities at transaction level */
10988         /* BUG Fixes : 4472308 and 4065967 */
10989         for i in 0 .. 7 loop
10990           tempDoRelativePriorities := engPriorityModes(i) = ame_util.relativeRulePriority;
10991           if tempDoRelativePriorities then
10992             ruleExists := false;
10993             tempIndex := engAppRuleIds.first;
10994             loop
10995               if engAppRuleTypes(tempIndex) = i then
10996                 if engAppPriorities(tempIndex) is null then
10997                   tempThresholds(99999) := engAppPriorities(tempIndex);
10998                 else
10999                   tempThresholds(engAppPriorities(tempIndex)) := engAppPriorities(tempIndex);
11000                 end if;
11001                 ruleExists := true;
11002               end if;
11003               tempIndex := engAppRuleIds.next(tempIndex);
11004               exit when tempIndex is null;
11005             end loop;
11006             if ruleExists then
11007               tempAbsoluteThreshold := tempThresholds.first;
11008               tempThresholdCounter := 1;
11009               currentThreshold := engPriorityThresholds(i);
11010               while (tempThresholdCounter < currentThreshold) loop
11011                 tempAbsoluteThreshold := tempThresholds.next(tempAbsoluteThreshold);
11012                 tempThresholdCounter := tempThresholdCounter + 1;
11013               end loop;
11014               tempIndex := engAppRuleIds.first;
11015               loop
11016                 if(engAppRuleTypes(tempIndex) = i and
11017                    (engAppPriorities(tempIndex) is null or
11018                     engAppPriorities(tempIndex) > tempAbsoluteThreshold)) then
11019                   oldTempIndex := tempIndex;
11020                   tempIndex := engAppRuleIds.next(oldTempIndex);
11021                   engAppRuleIds.delete(oldTempIndex);
11022                   engRuleAppliedYN.delete(oldTempIndex);
11023                   engAppItemClassIds.delete(oldTempIndex);
11024                   engAppItemIds.delete(oldTempIndex);
11025                   engAppPriorities.delete(oldTempIndex);
11026                   engAppApproverCategories.delete(oldTempIndex);
11027                   engAppRuleTypes.delete(oldTempIndex);
11028                   engAppRuleItemClassIds.delete(oldTempIndex);
11029                   engAppAppItemIds.delete(oldTempIndex);
11030                   ruleDeleted := true;
11031                 else
11032                   tempIndex := engAppRuleIds.next(tempIndex);
11033                 end if;
11034                 exit when tempIndex is null;
11035               end loop;
11036             end if;
11037           end if;
11038         end loop;
11039       end if;
11040       /* If relative-priority processing deleted one or more rules from the engApp lists, compact them. */
11041       if(ruleDeleted) then
11042         compactEngAppLists(compactPrioritiesIn => true,
11043                            compactActionTypeIdsIn => false,
11044                            compactParametersIn => false);
11045       end if;
11046       exception
11047         when others then
11048           ame_util.runtimeException(packageNameIn => 'ame_engine',
11049                                     routineNameIn => 'processRelativePriorities',
11050                                     exceptionNumberIn => sqlcode,
11051                                     exceptionStringIn => sqlerrm);
11052           raise;
11053     end processRelativePriorities;
11054   procedure processUnresponsiveApprovers as
11055     engStApproversCount integer;
11056     tempIndex integer;
11057     tempSurrogateApprover ame_util.approverRecord2;
11058     begin
11059       /* First handle the empty-list case. */
11060       engStApproversCount := engStApprovers.count;
11061       if(engStApproversCount = 0) then
11062         return;
11063       end if;
11064       /* Now handle the non-empty case. */
11065       tempIndex := 1; /* post-increment */
11066       loop
11067         if(engStApprovers(tempIndex).approval_status = ame_util.noResponseStatus) then
11068           /* Fetch surrogate's wf_roles-specific data. */
11069           ame_approver_type_pkg.getSurrogate(origSystemIn => engStApprovers(tempIndex).orig_system,
11070                                              origSystemIdIn => engStApprovers(tempIndex).orig_system_id,
11071                                              origSystemIdOut => tempSurrogateApprover.orig_system_id,
11072                                              wfRolesNameOut => tempSurrogateApprover.name,
11073                                              displayNameOut => tempSurrogateApprover.display_name);
11074           tempSurrogateApprover.orig_system := engStApprovers(tempIndex).orig_system;
11075           /* Set fields constant for all surrogates. */
11076           tempSurrogateApprover.api_insertion := ame_util.apiInsertion;
11077           tempSurrogateApprover.source := ame_util.surrogateInsertion;
11078           /* Set common-valued fields. */
11079           tempSurrogateApprover.approver_category := engStApprovers(tempIndex).approver_category;
11080           tempSurrogateApprover.authority := engStApprovers(tempIndex).authority;
11081           tempSurrogateApprover.action_type_id := engStApprovers(tempIndex).action_type_id;
11082           tempSurrogateApprover.group_or_chain_id := engStApprovers(tempIndex).group_or_chain_id;
11083           tempSurrogateApprover.item_class := engStApprovers(tempIndex).item_class;
11084           tempSurrogateApprover.item_id := engStApprovers(tempIndex).item_id;
11085           tempSurrogateApprover.item_class_order_number := engStApprovers(tempIndex).item_class_order_number;
11086           tempSurrogateApprover.item_order_number := engStApprovers(tempIndex).item_order_number;
11087           tempSurrogateApprover.sub_list_order_number := engStApprovers(tempIndex).sub_list_order_number;
11088           tempSurrogateApprover.action_type_order_number := engStApprovers(tempIndex).action_type_order_number;
11089           tempSurrogateApprover.group_or_chain_order_number := engStApprovers(tempIndex).group_or_chain_order_number;
11090           /* Set remaining fields. */
11091           tempSurrogateApprover.occurrence :=
11092             getHandlerOccurrence(nameIn => tempSurrogateApprover.name,
11093                                  itemClassIn => tempSurrogateApprover.item_class,
11094                                  itemIdIn => tempSurrogateApprover.item_id,
11095                                  actionTypeIdIn => tempSurrogateApprover.action_type_id,
11096                                  groupOrChainIdIn => tempSurrogateApprover.group_or_chain_id);
11097           tempSurrogateApprover.approval_status := getHandlerApprovalStatus(approverIn => tempSurrogateApprover);
11098           /* The member order number and the approver order number are set here
11099              instead of in insertApprover. This will ensure that the surrogate has the same
11100              order as the unresponsive approver. Also changed call to insertApprover so that
11101              adjustMemberOrderNumbers is false */
11102           tempSurrogateApprover.member_order_number := engStApprovers(tempIndex).member_order_number;
11103           tempSurrogateApprover.approver_order_number := engStApprovers(tempIndex).approver_order_number;
11104           /* tempSurrogateApprover.approver_order_number also gets set later. */
11105           if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
11106             fnd_log.string
11107               (fnd_log.level_statement
11108               ,'ame_engine.processUnresponsiveApprovers'
11109               ,'Unresponsive approver ::: ' || engStApprovers(tempIndex).name || ' Surrogate ::: ' || tempSurrogateApprover.name
11110               );
11111           end if;
11112           engTempReason := ame_approver_deviation_pkg.timeoutReason;
11113           engTempDate := sysdate;
11114           insertApprover(indexIn => tempIndex + 1,
11115                          approverIn => tempSurrogateApprover,
11116                          adjustMemberOrderNumbersIn => false);
11117           engStApproversCount := engStApproversCount + 1;
11118         end if;
11119         if(tempIndex = engStApproversCount) then
11120           exit;
11121         end if;
11122         tempIndex := tempIndex + 1;
11123       end loop;
11124       exception
11125         when others then
11126           ame_util.runtimeException(packageNameIn => 'ame_engine',
11127                                     routineNameIn => 'processUnresponsiveApprovers',
11128                                     exceptionNumberIn => sqlcode,
11129                                     exceptionStringIn => sqlerrm);
11130           raise;
11131     end processUnresponsiveApprovers;
11132   procedure repeatSubstitutions as
11133     currentActionTypeId integer;
11134     begin
11135       /* Check if any substitution rule exists. This can be done by checking if
11136          engAppSubHandlerFirstIndex  is null or not */
11137       if not(engAppSubHandlerFirstIndex  is null or
11138              engAppSubHandlerLastIndex is null) then
11139         /* Initialize the action-type state variables. */
11140         engAppHandlerFirstIndex := engAppSubHandlerFirstIndex;
11141         engAppHandlerLastIndex := engAppSubHandlerLastIndex;
11142         processActionType;
11143       end if;
11144     end repeatSubstitutions;
11145   procedure setContext(isTestTransactionIn in boolean,
11146                        isLocalTransactionIn in boolean,
11147                        fetchConfigVarsIn in boolean,
11148                        fetchOldApproversIn in boolean,
11149                        fetchInsertionsIn in boolean,
11150                        fetchDeletionsIn in boolean,
11151                        fetchAttributeValuesIn in boolean,
11152                        fetchInactiveAttValuesIn in boolean,
11153                        processProductionActionsIn in boolean,
11154                        processProductionRulesIn in boolean,
11155                        updateCurrentApproverListIn in boolean,
11156                        updateOldApproverListIn in boolean,
11157                        processPrioritiesIn in boolean,
11158                        prepareItemDataIn in boolean,
11159                        prepareRuleIdsIn in boolean,
11160                        prepareRuleDescsIn in boolean,
11161                        prepareApproverTreeIn in boolean default false,
11162                        transactionIdIn in varchar2,
11163                        ameApplicationIdIn in integer default null,
11164                        fndApplicationIdIn in integer default null,
11165                        transactionTypeIdIn in varchar2 default null) as
11166     badLocalTransException exception;
11167     errorCode integer;
11168     errorMessage ame_util.longestStringType;
11169     nullValuesException exception;
11170     tempConfigVarValue ame_config_vars.variable_value%type;
11171     begin
11172       /*
11173         Clear all of the package variables, to be conservative.  (The application server does not initialize
11174         package variables.  See http://www-apps.us.oracle.com/atg/plans/r1153/plsqlglobals.txt for details.)
11175       */
11176       engLMParameterOnes.delete;
11177       engLMParameterTwos.delete;
11178       engGroupMemberGroupIds.delete;
11179       engGroupMemberNames.delete;
11180       engGroupMemberOrderNumbers.delete;
11181       engGroupMemberDisplayNames.delete;
11182       engGroupMemberOrigSystems.delete;
11183       engGroupMemberOrigSystemIds.delete;
11184       engGroupUseItemBind.delete;
11185       engAppActionTypeIds.delete;
11186       engAppApproverCategories.delete;
11187       engAppItemClassIds.delete;
11188       engAppItemIds.delete;
11189       engAppLMSubItemClassIds.delete;
11190       engAppLMSubItemIds.delete;
11191       engAppParameters.delete;
11192       engAppParameterTwos.delete;
11193       engAppPriorities.delete;
11194       engAppRuleIds.delete;
11195       engRuleAppliedYN.delete;
11196       engAppRuleTypes.delete;
11197       engAppRuleItemClassIds.delete;
11198       engAppAppItemIds.delete;
11199       engAppPerAppProdFirstIndexes.delete;
11200       engAppPerAppProdRuleIds.delete;
11201       engAppPerAppProdVariableNames.delete;
11202       engAppPerAppProdVariableValues.delete;
11203       engStApprovers.delete;
11204       /* Clear the engine approver tree */
11205       engStApproversTree.delete;
11206       engStItemClasses.delete;
11207       engStItemIds.delete;
11208       engStItemIndexes.delete;
11209       engStItemSources.delete;
11210       engStProductionIndexes.delete;
11211       /* Clear repeated indexes list */
11212       engStRepeatedIndexes.delete;
11213       engStRepeatedAppIndexes.delete;
11214       engStRuleDescriptions.delete;
11215       engStRuleIds.delete;
11216       engStRuleIndexes.delete;
11217       engStSourceTypes.delete;
11218       /* Clear suspended items list */
11219       engStSuspendedItems.delete;
11220       engStSuspendedItemClasses.delete;
11221       engStProductionsTable.delete;
11222       engStVariableNames.delete;
11223       engStVariableValues.delete;
11224       engStItemAppProcessCompleteYN.delete;
11225       engConfigVarNames.delete;
11226       engConfigVarValues.delete;
11227       engForwardingBehaviors.delete;
11228       engPriorityModes.delete;
11229       engPriorityThresholds.delete;
11230       engActionTypeChainOrderModes.delete;
11231       engActionTypeOrderNumbers.delete;
11232       engActionTypeVotingRegimes.delete;
11233       engActionTypeNames.delete;
11234       engActionTypeUsages.delete;
11235       engActionTypePackageNames.delete;
11236       engItemClassIds.delete;
11237       engItemClassIndexes.delete;
11238       engItemClassItemIdIndexes.delete;
11239       engItemClassNames.delete;
11240       engItemClassOrderNumbers.delete;
11241       engItemClassParModes.delete;
11242       engItemClassSublistModes.delete;
11243       engItemCounts.delete;
11244       engItemIds.delete;
11245       engAttributeIsStatics.delete;
11246       engAttributeItemClassIds.delete;
11247       engAttributeNames.delete;
11248       engAttributeTypes.delete;
11249       engAttributeValueIndexes.delete;
11250       engAttributeValues1.delete;
11251       engAttributeValues2.delete;
11252       engAttributeValues3.delete;
11253       engAttributeQueries.delete;
11254       engAttributeVariant.delete;
11255       engHeaderConditionValues.delete;
11256       engACUsageConditionIds.delete;
11257       engACUsageFirstIndexes.delete;
11258       engACUsageItemClassCounts.delete;
11259       engACUsageRuleIds.delete;
11260       engACUsageRulePriorities.delete;
11261       engACUsageRuleTypes.delete;
11262       engACUsageRuleApprCategories.delete;
11263       engACAttributeIds.delete;
11264       engACConditionTypes.delete;
11265       engACIncludeLowerLimits.delete;
11266       engACIncludeUpperLimits.delete;
11267       engACParameterOnes.delete;
11268       engACParameterThrees.delete;
11269       engACParameterTwos.delete;
11270       engACStringValueCounts.delete;
11271       engACStringValueFirstIndexes.delete;
11272       engACStringValues.delete;
11273       engOldApproverList.delete;
11274       engInsertedApproverList.delete;
11275       engInsertionOrderTypeList.delete;
11276       engInsertionParameterList.delete;
11277       engInsertionIsSpecialForwardee.delete;
11278       engDeletedApproverList.delete;
11279       engStInsertionIndexes.delete;
11280       /*delete deviation related info*/
11281       engDeviationResultList.delete;
11282       engInsertionReasonList.delete;
11283       engInsertionDateList.delete;
11284       engSuppressionDateList.delete;
11285       engSupperssionReasonList.delete;
11286       engInsApproverIndex.delete;
11287       engTempReason := null;
11288       engTempDate := null;
11289       /* Fetch the transaction identifiers. */
11290       if(ameApplicationIdIn is null) then
11291         if(fndApplicationIdIn is null) then
11292           raise nullValuesException;
11293         end if;
11294         engFndApplicationId := fndApplicationIdIn;
11295         engTransactionTypeId := transactionTypeIdIn;
11296         engAmeApplicationId := fetchAmeApplicationId(fndApplicationIdIn => fndApplicationIdIn,
11297                                                      transactionTypeIdIn => transactionTypeIdIn);
11298       else
11299         engAmeApplicationId := ameApplicationIdIn;
11300         fetchFndApplicationId(applicationIdIn => ameApplicationIdIn,
11301                               fndApplicationIdOut => engFndApplicationId,
11302                               transactionTypeIdOut => engTransactionTypeId);
11303       end if;
11304       engTransactionId := transactionIdIn;
11305       engIsTestTransaction := isTestTransactionIn;
11306       engIsLocalTransaction := isLocalTransactionIn;
11307       if(engIsTestTransaction and not engIsLocalTransaction) then
11308         raise badLocalTransException;
11309       end if;
11310       /* Initialize engEffectiveRuleDate to sysdate, in case the attribute values aren't fetched. */
11311       engEffectiveRuleDate := sysdate;
11312       /* Initialize misc. boolean globals to the corresponding input values. */
11313       engPrepareItemData := prepareItemDataIn;
11314       engPrepareRuleIds := prepareRuleIdsIn;
11315       engPrepareRuleDescs := prepareRuleDescsIn;
11316       engPrepareApproverTree := prepareApproverTreeIn;
11317       engItemDataPrepared := false;
11318       engProcessProductionActions := processProductionActionsIn;
11319       engProcessProductionRules := processProductionRulesIn;
11320       engProcessPriorities := processPrioritiesIn;
11321       engUpdateCurrentApproverList := updateCurrentApproverListIn;
11322       engUpdateOldApproverList := updateOldApproverListIn;
11323       /* Optionally fetch the global configuration-variable lists. */
11324       if(fetchConfigVarsIn) then
11325         /* Fetch. */
11326         fetchConfigVars;
11327         /* Reconcile the engProcessProduction values with the productionFunctionality config var. */
11328         tempConfigVarValue := getConfigVarValue(configVarNameIn => ame_util.productionConfigVar);
11329         if(engProcessProductionActions and
11330            tempConfigVarValue in (ame_util.noProductions, ame_util.perTransactionProductions)) then
11331           engProcessProductionActions := false;
11332         end if;
11333         if(engProcessProductionRules and
11334            tempConfigVarValue in (ame_util.noProductions, ame_util.perApproverProductions)) then
11335           engProcessProductionRules := false;
11336         end if;
11337       end if;
11338       /* Optionally fetch the transaction's attribute values.  */
11339       if(fetchAttributeValuesIn) then
11340         /* Go fetch. */
11341         fetchItemClassData;
11342         fetchAttributeValues(fetchInactivesIn => fetchInactiveAttValuesIn);
11343         /* Set misc. frequently-used attribute-value caches. */
11344         engEvalPrioritiesPerItem :=
11345           getHeaderAttValue2(attributeNameIn => ame_util.evalPrioritiesPerItemAttribute) =
11346             ame_util.booleanAttributeTrue;
11347         engRepeatSubstitutions  :=
11348           getHeaderAttValue2(attributeNameIn => ame_util.repeatSubstitutionsAttribute) =
11349             ame_util.booleanAttributeTrue;
11350         /* A null effective rule date should be interpreted as sysdate. */
11351         engEffectiveRuleDate := ame_util.versionStringToDate(stringDateIn =>
11352           getHeaderAttValue2(attributeNameIn => ame_util.effectiveRuleDateAttribute));
11353         if(engEffectiveRuleDate is null) then
11354           engEffectiveRuleDate := sysdate;
11355         else
11356           -- evaluate the attributes with use count 0 if they are used in rules
11357           -- which were active as of effective_rule_date.
11358           if not fetchInactiveAttValuesIn then
11359             fetchOtherAttributeValues;
11360           end if;
11361         end if;
11362         if(processProductionActionsIn or
11363            processProductionRulesIn or
11364            updateCurrentApproverListIn or
11365            updateOldApproverListIn or
11366            processPrioritiesIn or
11367            prepareItemDataIn or
11368            prepareRuleIdsIn or
11369            prepareRuleDescsIn) then
11370           /* Fetch the active condition usages. */
11371           fetchActiveConditionUsages;
11372         end if;
11373       end if;
11374       /* Optionally fetch the old approver list. */
11375       if(fetchOldApproversIn) then
11376         fetchOldApprovers;
11377       end if;
11378       /* Optionally fetch the inserted-approvers list. */
11379       if(fetchInsertionsIn) then
11380         fetchInsertedApprovers;
11381       end if;
11382       /* Optionally fetch the approver-deletions list. */
11383       if(fetchDeletionsIn) then
11384         fetchDeletedApprovers;
11385       end if;
11386       exception
11387         when badLocalTransException then
11388           errorCode := -20001;
11389           errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
11390                                               messageNameIn => 'AME_400688_ENG_TESTTX_NONLOCAL');
11391           ame_util.runtimeException(packageNameIn => 'ame_engine',
11392                                     routineNameIn => 'setContext',
11393                                     exceptionNumberIn => errorCode,
11394                                     exceptionStringIn => errorMessage);
11395           raise_application_error(errorCode,
11396                                   errorMessage);
11397         when nullValuesException then
11398           errorCode := -20001;
11399           errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
11400                                               messageNameIn => 'AME_400129_ENG_APPLID_NULL');
11401           ame_util.runtimeException(packageNameIn => 'ame_engine',
11402                                     routineNameIn => 'setContext',
11403                                     exceptionNumberIn => errorCode,
11404                                     exceptionStringIn => errorMessage);
11405           raise_application_error(errorCode,
11406                                   errorMessage);
11407         when others then
11408           ame_util.runtimeException(packageNameIn => 'ame_engine',
11409                                     routineNameIn => 'setContext',
11410                                     exceptionNumberIn => sqlcode,
11411                                     exceptionStringIn => sqlerrm);
11412           raise;
11413     end setContext;
11414   procedure setHandlerState(handlerNameIn in varchar2,
11415                             parameterIn in varchar2 default null,
11416                             stateIn in varchar2 default null) as
11417     argumentLengthException exception;
11418     errorCode integer;
11419     errorMessage ame_util.longestStringType;
11420     handlerName ame_temp_handler_states.handler_name%type;
11421     begin
11422       if(lengthb(stateIn) > 100 or
11423          lengthb(parameterIn) > 100) then
11424         raise argumentLengthException;
11425       end if;
11426       handlerName := upper(handlerNameIn);
11427       delete
11428         from ame_temp_handler_states
11429         where
11430           handler_name = handlerName and
11431           application_id = engAmeApplicationId and
11432           ((parameter is null and parameterIn is null) or
11433            (parameter = parameterIn));
11434       insert into ame_temp_handler_states(
11435         handler_name,
11436         row_timestamp,
11437         application_id,
11438         parameter,
11439         state)
11440         values(
11441           handlerName,
11442           sysdate, /* Don't use engEffectiveRuleDate here. */
11443           engAmeApplicationId,
11444           parameterIn,
11445           stateIn);
11446       exception
11447         when argumentLengthException then
11448           errorCode := -20001;
11449           errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
11450                                               messageNameIn => 'AME_400130_ENG_HDLR_PAR_LNG');
11451           ame_util.runtimeException(packageNameIn => 'ame_engine',
11452                                     routineNameIn => 'setHandlerState',
11453                                     exceptionNumberIn => errorCode,
11454                                     exceptionStringIn => errorMessage);
11455           raise_application_error(errorCode,
11456                                   errorMessage);
11457         when others then
11458           ame_util.runtimeException(packageNameIn => 'ame_engine',
11459                                     routineNameIn => 'setHandlerState',
11460                                     exceptionNumberIn => sqlcode,
11461                                     exceptionStringIn => sqlerrm);
11462           raise;
11463     end setHandlerState;
11464   procedure setInsertedApprovalStatus(currentApproverIndexIn in integer
11465                                       ,approvalStatusIn in varchar2) as
11466     begin
11467       for i in 1..engInsApproverIndex.count loop
11468         if engInsApproverIndex(i) = currentApproverIndexIn then
11469           engInsertedApproverList(i).approval_status := approvalStatusIn;
11470           update ame_temp_insertions
11471              set approval_status = approvalStatusIn
11472           where application_id = engAmeApplicationId
11473            and transaction_id = engTransactionId
11474            and insertion_order = engInsertionOrderList(i)
11475            and order_type = engInsertionOrderTypeList(i)
11476            and parameter = engInsertionParameterList(i)
11477            and api_insertion = engInsertedApproverList(i).api_insertion
11478            and authority = engInsertedApproverList(i).authority;
11479          return;
11480         end if;
11481       end loop;
11482     exception
11483       when others then
11484         ame_util.runtimeException(packageNameIn => 'ame_engine',
11485                                   routineNameIn => 'setInsertedApprovalStatus',
11486                                   exceptionNumberIn => sqlcode,
11487                                   exceptionStringIn => sqlerrm);
11488           raise;
11489   end setInsertedApprovalStatus;
11490   procedure setRuleApplied(ruleIndexIn in integer) as
11491     begin
11492       engRuleAppliedYN(ruleIndexIn) := ame_util.booleanTrue;
11493     end setRuleApplied;
11494   procedure sortApplicableRules(sortByActionTypeIn in boolean) as
11495     exchangeActionTypeId integer;
11496     exchangeAppItemId ame_util.stringType;
11497     exchangeApproverCategory ame_util.charType;
11498     exchangeItemClassId integer;
11499     exchangeItemId ame_util.stringType;
11500     exchangeParameter ame_actions.parameter%type;
11501     exchangeParameterTwo ame_actions.parameter_two%type;
11502     exchangePriority integer;
11503     exchangeRuleId integer;
11504     exchangeRuleItemClassId integer;
11505     exchangeRuleType ame_util.stringType;
11506     exchangeRuleAppliedYN ame_util.charType;
11507     begin
11508       /*
11509         This is a simple sort algorithm, but it is efficient for small input counts.
11510         The inputs are generally nearly sorted, which makes at least a nonrandomized
11511         quicksort a poor choice (quicksort's worst-case performance arises in the
11512         case of inputs that are already sorted or nearly sorted).  A randomized
11513         quicksort would avoid this problem, but our judgment is that the random-number
11514         generation overhead makes this approach undesirable for inputs of the sizes
11515         we expect.
11516       */
11517       for i in 2 .. engAppRuleIds.count loop
11518         for j in 1 .. i - 1 loop
11519           if(compareApplicableRules(index1In => i,
11520                                     index2In => j,
11521                                     compareActionTypesIn => sortbyActionTypeIn)) then
11522             /* Set exchange buffers' values. */
11523             exchangeItemClassId := engAppItemClassIds(i);
11524             exchangeItemId := engAppItemIds(i);
11525             exchangeRuleItemClassId := engAppRuleItemClassIds(i);
11526             exchangeAppItemId := engAppAppItemIds(i);
11527             exchangeRuleId := engAppRuleIds(i);
11528             exchangeRuleAppliedYN := engRuleAppliedYN(i);
11529             exchangeRuleType := engAppRuleTypes(i);
11530             exchangeApproverCategory := engAppApproverCategories(i);
11531             if(sortByActionTypeIn) then
11532               exchangeActionTypeId := engAppActionTypeIds(i);
11533               exchangeParameter := engAppParameters(i);
11534               exchangeParameterTwo := engAppParameterTwos(i);
11535             elsif(engProcessPriorities) then
11536               exchangePriority := engAppPriorities(i);
11537             end if;
11538             /* Move jth values to index i. */
11539             engAppRuleItemClassIds(i) := engAppRuleItemClassIds(j);
11540             engAppAppItemIds(i) := engAppAppItemIds(j);
11541             engAppItemClassIds(i) := engAppItemClassIds(j);
11542             engAppItemIds(i) := engAppItemIds(j);
11543             engAppRuleIds(i) := engAppRuleIds(j);
11544             engRuleAppliedYN(i) := engRuleAppliedYN(j);
11545             engAppRuleTypes(i) := engAppRuleTypes(j);
11546             engAppApproverCategories(i) := engAppApproverCategories(j);
11547             if(sortByActionTypeIn) then
11548               engAppActionTypeIds(i) := engAppActionTypeIds(j);
11549               engAppParameters(i) := engAppParameters(j);
11550               engAppParameterTwos(i) := engAppParameterTwos(j);
11551             elsif(engProcessPriorities) then
11552               engAppPriorities(i) := engAppPriorities(j);
11553             end if;
11554             /* Move buffered ith values to index j. */
11555             engAppRuleItemClassIds(j) := exchangeRuleItemClassId;
11556             engAppAppItemIds(j) := exchangeAppItemId;
11557             engAppItemClassIds(j) := exchangeItemClassId;
11558             engAppItemIds(j) := exchangeItemId;
11559             engAppRuleIds(j) := exchangeRuleId;
11560             engRuleAppliedYN(j) := exchangeRuleAppliedYN;
11561             engAppRuleTypes(j) := exchangeRuleType;
11562             engAppApproverCategories(j) := exchangeApproverCategory;
11563             if(sortByActionTypeIn) then
11564               engAppActionTypeIds(j) := exchangeActionTypeId;
11565               engAppParameters(j) := exchangeParameter;
11566               engAppParameterTwos(j) := exchangeParameterTwo;
11567             elsif(engProcessPriorities) then
11568               engAppPriorities(j) := exchangePriority;
11569             end if;
11570           end if;
11571         end loop;
11572       end loop;
11573       exception
11574         when others then
11575           ame_util.runtimeException(packageNameIn => 'ame_engine',
11576                                     routineNameIn => 'sortApplicableRules',
11577                                     exceptionNumberIn => sqlcode,
11578                                     exceptionStringIn => sqlerrm);
11579           raise;
11580     end sortApplicableRules;
11581   procedure substituteApprover(approverIndexIn in integer,
11582                                nameIn in varchar2,
11583                                actionTypeIdIn in varchar2,
11584                                ruleIdIn in integer) as
11585     currentActionTypeId integer;
11586     currentGroupOrChainId integer;
11587     occurrence integer;
11588     begin
11589       /* Look up the orig_system, orig_system_id, and display_name values corresponding to nameIn. */
11590       ame_approver_type_pkg.getOrigSystemIdAndDisplayName(
11591         nameIn => nameIn,
11592         origSystemOut => engStApprovers(approverIndexIn).orig_system,
11593         origSystemIdOut => engStApprovers(approverIndexIn).orig_system_id,
11594         displayNameOut => engStApprovers(approverIndexIn).display_name);
11595       /* Calculate the occurrence value for the substitution. */
11596       currentGroupOrChainId := engStApprovers(approverIndexIn).group_or_chain_id;
11597       occurrence := 1;
11598       for i in reverse 1 .. (approverIndexIn - 1) loop
11599         if(currentGroupOrChainId <> engStApprovers(i).group_or_chain_id or
11600            engStApprovers(approverIndexIn).action_type_id <> engStApprovers(i).action_type_id or
11601            engStApprovers(approverIndexIn).item_id <> engStApprovers(i).item_id or
11602            engStApprovers(approverIndexIn).item_class <> engStApprovers(i).item_class) then
11603           exit;
11604         end if;
11605         if(nameIn = engStApprovers(i).name) then
11606           occurrence := occurrence + 1;
11607         end if;
11608       end loop;
11609       engStApprovers(approverIndexIn).name := nameIn;
11610       engStApprovers(approverIndexIn).occurrence := occurrence;
11611       /* Get and set the approval status. */
11612       engStApprovers(approverIndexIn).approval_status :=
11613         getHandlerApprovalStatus(approverIn => engStApprovers(approverIndexIn));
11614       /* Append ruleIdIn to source value. */
11615       ame_util.appendRuleIdToSource(ruleIdIn => ruleIdIn,
11616                                     sourceInOut => engStApprovers(approverIndexIn).source);
11617       /* Update the occurrence values of the same approver wherever the approver occurs later in the same chain. */
11618       for i in approverIndexIn + 1 .. engStApprovers.count loop
11619         if(currentGroupOrChainId <> engStApprovers(i).group_or_chain_id or
11620            engStApprovers(approverIndexIn).action_type_id <> engStApprovers(i).action_type_id or
11621            engStApprovers(approverIndexIn).item_id <> engStApprovers(i).item_id or
11622            engStApprovers(approverIndexIn).item_class <> engStApprovers(i).item_class) then
11623           exit;
11624         end if;
11625         if(nameIn = engStApprovers(i).name) then
11626           occurrence := occurrence + 1;
11627           engStApprovers(i).occurrence := occurrence;
11628           /* Get and set the approval status for this approver's approval status. */
11629           engStApprovers(i).approval_status :=
11630             getHandlerApprovalStatus(approverIn => engStApprovers(i));
11631         end if;
11632       end loop;
11633       exception
11634         when others then
11635           ame_util.runtimeException(packageNameIn => 'ame_engine',
11636                                     routineNameIn => 'substituteApprover',
11637                                     exceptionNumberIn => sqlcode,
11638                                     exceptionStringIn => sqlerrm);
11639           raise;
11640     end substituteApprover;
11641   procedure truncateChain(approverIndexIn in integer,
11642                           ruleIdIn in integer) as
11643     currentActionTypeId integer;
11644     currentGroupOrChainId integer;
11645     engStApproversCount integer;
11646     firstIndexToTruncate integer;
11647     lastIndexToTruncate integer;
11648     siblingTreeNodeIndex integer;
11649     tempIndex integer;
11650     truncateCount integer;
11651     loopIndex integer;
11652     nextIndex integer;
11653     begin
11654       /*
11655         This procedure copies the current action-type ID and group-or-chain ID into local
11656         variables for efficiency, but does not copy the item ID or item class because these
11657         copy operations are likely to take much longer, and to require substantially more
11658         memory-allocation overhead.
11659       */
11660       currentActionTypeId := engStApprovers(approverIndexIn).action_type_id;
11661       currentGroupOrChainId := engStApprovers(approverIndexIn).group_or_chain_id;
11662       engStApproversCount := engStApprovers.count;
11663       /* First handle the case where no truncation is required. */
11664       tempIndex := approverIndexIn + 1;
11665       if(approverIndexIn = engStApproversCount or
11666          currentGroupOrChainId <> engStApprovers(tempIndex).group_or_chain_id or
11667          currentActionTypeId <> engStApprovers(tempIndex).action_type_id or
11668          engStApprovers(approverIndexIn).item_id <> engStApprovers(tempIndex).item_id or
11669          engStApprovers(approverIndexIn).item_class <> engStApprovers(tempIndex).item_class) then
11670         return;
11671       end if;
11672       /* Evidently the approver at tempIndex is in the same chain.  Find the last approver in that chain. */
11673       firstIndexToTruncate := tempIndex;
11674       lastIndexToTruncate := firstIndexToTruncate;
11675       for i in firstIndexToTruncate + 1 .. engStApproversCount loop
11676         /* Stop at the end of the chain. */
11677         if(currentGroupOrChainId <> engStApprovers(i).group_or_chain_id or
11678            currentActionTypeId <> engStApprovers(i).action_type_id or
11679            engStApprovers(approverIndexIn).item_id <> engStApprovers(i).item_id or
11680            engStApprovers(approverIndexIn).item_class <> engStApprovers(i).item_class) then
11681           lastIndexToTruncate := i - 1;
11682           exit;
11683         end if;
11684         if(i = engStApproversCount) then
11685           lastIndexToTruncate := engStApproversCount;
11686         end if;
11687       end loop;
11688       /*
11689         Truncate from the first index to the last index, inclusive.
11690          delete the rest of the chain.
11691       */
11692       truncateCount := lastIndexToTruncate - firstIndexToTruncate + 1;
11693       /* Copy the end of the list down truncateCount places. */
11694       for i in firstIndexToTruncate .. (engStApproversCount - truncateCount) loop
11695         ame_util.copyApproverRecord2(approverRecord2In => engStApprovers(i + truncateCount),
11696                                      approverRecord2Out => engStApprovers(i));
11697       end loop;
11698       /* Code to delete the approvers from the tree whenever there are approver suppressions */
11699       if engPrepareApproverTree then
11700         siblingTreeNodeIndex := ame_util.noSiblingIndex;
11701         /* Approvers Tree is sparse */
11702         loopIndex := engStApproversTree.last;
11703         loop
11704           if engStApproversTree(loopIndex).tree_level = 6 then
11705             if engStApproversTree(loopIndex).approver_index >= firstIndexToTruncate + truncateCount then
11706               engStApproversTree(loopIndex).approver_index := engStApproversTree(loopIndex).approver_index - truncateCount;
11707               nextIndex := engStApproversTree.prior(loopIndex);
11708             elsif engStApproversTree(loopIndex).approver_index >= firstIndexToTruncate
11709                   and engStApproversTree(loopIndex).approver_index < lastIndexToTruncate then
11710               nextIndex := engStApproversTree.prior(loopIndex);
11711               engStApproversTree.delete(loopIndex);
11712             elsif engStApproversTree(loopIndex).approver_index = lastIndexToTruncate then
11713               siblingTreeNodeIndex := engStApproversTree(loopIndex).sibling_index;
11714               nextIndex := engStApproversTree.prior(loopIndex);
11715               engStApproversTree.delete(loopIndex);
11716             elsif engStApproversTree(loopIndex).approver_index = firstIndexToTruncate - 1 then
11717               engStApproversTree(loopIndex).sibling_index := siblingTreeNodeIndex;
11718               nextIndex := engStApproversTree.prior(loopIndex);
11719             else
11720               nextIndex := engStApproversTree.prior(loopIndex);
11721             end if;
11722           else
11723             nextIndex := engStApproversTree.prior(loopIndex);
11724           end if;
11725           exit when engStApproversTree.first = nextIndex;
11726           loopIndex := nextIndex;
11727         end loop;
11728       end if;
11729       /* Delete the last truncateCount places. */
11730       engStApprovers.delete(engStApproversCount - truncateCount + 1, engStApproversCount);
11731       exception
11732         when others then
11733           ame_util.runtimeException(packageNameIn => 'ame_engine',
11734                                     routineNameIn => 'truncateChain',
11735                                     exceptionNumberIn => sqlcode,
11736                                     exceptionStringIn => sqlerrm);
11737           raise;
11738     end truncateChain;
11739   procedure unlockTransaction(fndApplicationIdIn in integer,
11740                               transactionIdIn in varchar2,
11741                               transactionTypeIdIn in varchar2 default null) as
11742     begin
11743       if(engTransactionIsLocked) then
11744         delete from ame_temp_trans_locks
11745           where
11746             fnd_application_id = fndApplicationIdIn and
11747             ((transaction_type_id is null and transactionTypeIdIn is null) or
11748              transaction_type_id = transactionTypeIdIn) and
11749             transaction_id = transactionIdIn;
11750       end if;
11751       engTransactionIsLocked := false;
11752       exception
11753          when others then
11754           ame_util.runtimeException(packageNameIn => 'ame_engine',
11755                                     routineNameIn => 'unlockTransaction',
11756                                     exceptionNumberIn => sqlcode,
11757                                     exceptionStringIn => sqlerrm);
11758           raise;
11759     end unlockTransaction;
11760   procedure updateTransactionState(isTestTransactionIn in boolean,
11761                                    isLocalTransactionIn in boolean,
11762                                    fetchConfigVarsIn in boolean,
11763                                    fetchOldApproversIn in boolean,
11764                                    fetchInsertionsIn in boolean,
11765                                    fetchDeletionsIn in boolean,
11766                                    fetchAttributeValuesIn in boolean,
11767                                    fetchInactiveAttValuesIn in boolean,
11768                                    processProductionActionsIn in boolean,
11769                                    processProductionRulesIn in boolean,
11770                                    updateCurrentApproverListIn in boolean,
11771                                    updateOldApproverListIn in boolean,
11772                                    processPrioritiesIn in boolean,
11773                                    prepareItemDataIn in boolean,
11774                                    prepareRuleIdsIn in boolean,
11775                                    prepareRuleDescsIn in boolean,
11776                                    prepareApproverTreeIn in boolean default false,
11777                                    transactionIdIn in varchar2,
11778                                    ameApplicationIdIn in integer default null,
11779                                    fndApplicationIdIn in integer default null,
11780                                    transactionTypeIdIn in varchar2 default null) as
11781     configVarException exception;
11782     errorCode integer;
11783     errorMessage ame_util.longestStringType;
11784     begin
11785       setContext(isTestTransactionIn => isTestTransactionIn,
11786                  isLocalTransactionIn => isLocalTransactionIn,
11787                  fetchConfigVarsIn => fetchConfigVarsIn,
11788                  fetchOldApproversIn => fetchOldApproversIn,
11789                  fetchInsertionsIn => fetchInsertionsIn,
11790                  fetchDeletionsIn => fetchDeletionsIn,
11791                  fetchAttributeValuesIn => fetchAttributeValuesIn,
11792                  fetchInactiveAttValuesIn => fetchInactiveAttValuesIn,
11793                  processProductionActionsIn => processProductionActionsIn,
11794                  processProductionRulesIn => processProductionRulesIn,
11795                  updateCurrentApproverListIn => updateCurrentApproverListIn,
11796                  updateOldApproverListIn => updateOldApproverListIn,
11797                  processPrioritiesIn => processPrioritiesIn,
11798                  prepareItemDataIn => prepareItemDataIn,
11799                  prepareRuleIdsIn => prepareRuleIdsIn,
11800                  prepareRuleDescsIn => prepareRuleDescsIn,
11801                  prepareApproverTreeIn => prepareApproverTreeIn,
11802                  transactionIdIn => transactionIdIn,
11803                  ameApplicationIdIn => ameApplicationIdIn,
11804                  fndApplicationIdIn => fndApplicationIdIn,
11805                  transactionTypeIdIn => transactionTypeIdIn);
11806       if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
11807         fnd_log.string
11808           (fnd_log.level_statement
11809           ,'ame_engine.updateTransactionState'
11810           ,'AME Application Id ::: ' || engAmeApplicationId
11811           );
11812         fnd_log.string
11813           (fnd_log.level_statement
11814           ,'ame_engine.updateTransactionState'
11815           ,'AME Transaction Id ::: ' || engTransactionId
11816           );
11817       end if;
11818       /* Added from version 115.217 to log a transaction (backward compatiblity)*/
11819       if updateOldApproverListIn then
11820         logTransaction;
11821       end if;
11822       if(processProductionActionsIn or
11823          processProductionRulesIn or
11824          updateCurrentApproverListIn or
11825          updateOldApproverListIn or
11826          processPrioritiesIn or
11827          prepareItemDataIn or
11828          prepareRuleIdsIn or
11829          prepareRuleDescsIn) then
11830         if(not fetchConfigVarsIn) then
11831           raise configVarException;
11832         end if;
11833         evaluateRules;
11834         fetchApplicableActions;
11835         processExceptions;
11836       end if;
11837       if(updateCurrentApproverListIn or
11838          updateOldApproverListIn) then
11839         processRules(processOnlyProductionsIn => false);
11840       elsif(processProductionRulesIn) then
11841         processRules(processOnlyProductionsIn => true);
11842       end if;
11843       if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
11844         fnd_log.string
11845           (fnd_log.level_statement
11846           ,'ame_engine.updateTransactionState'
11847           ,'Approver count after processRules ::: ' || engStApprovers.count
11848           );
11849       end if;
11850       if(updateCurrentApproverListIn or
11851          updateOldApproverListIn) then
11852         processAdHocInsertions;
11853         if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
11854           fnd_log.string
11855             (fnd_log.level_statement
11856             ,'ame_engine.updateTransactionState'
11857             ,'Approver count after processAdHocInsertions ::: ' || engStApprovers.count
11858             );
11859         end if;
11860         processUnresponsiveApprovers;
11861         if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
11862           fnd_log.string
11863             (fnd_log.level_statement
11864             ,'ame_engine.updateTransactionState'
11865             ,'Approver count after processUnresponsiveApprovers ::: ' || engStApprovers.count
11866             );
11867         end if;
11868         if engRepeatSubstitutions  then
11869           repeatSubstitutions;
11870           if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
11871             fnd_log.string
11872               (fnd_log.level_statement
11873               ,'ame_engine.updateTransactionState'
11874               ,'Approver count after repeatSubstitutions ::: ' || engStApprovers.count
11875               );
11876           end if;
11877         end if;
11878 
11879         /*
11880           processSuppressions must precede processRepeatedApprovers, because the latter procedure needs to see
11881           any approver deletions, to aggregate approvers correctly.
11882         */
11883         processSuppressions;
11884         if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
11885           fnd_log.string
11886             (fnd_log.level_statement
11887             ,'ame_engine.updateTransactionState'
11888             ,'Approver count after processSuppressions ::: ' || engStApprovers.count
11889             );
11890         end if;
11891         /*
11892           processSuppressions must precede processRepeatedApprovers so every approver in engStApprovers still
11893           has non-null item_class and item_id fields.
11894         */
11895         processRepeatedApprovers;
11896         if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
11897           fnd_log.string
11898             (fnd_log.level_statement
11899             ,'ame_engine.updateTransactionState'
11900             ,'Approver count after processRepeatedApprovers ::: ' || engStApprovers.count
11901             );
11902         end if;
11903         /*
11904           processRepeatedApprovers must precede populateEngStVariables so the latter can treat repeated
11905           approvers as equivalent to approving approvers, for purposes of determining whether an item or
11906           transaction's approval process is complete.
11907         */
11908         populateEngStVariables;
11909         if engPrepareApproverTree then
11910           calculateApproverOrderNumbers;
11911           if updateOldApproverListIn then
11912             ame_approver_deviation_pkg.updateDeviationState(
11913                                          engAmeApplicationId
11914                                         ,engTransactionId
11915                                         ,engDeviationResultList
11916                                         ,engStApprovalProcessCompleteYN
11917                                         ,engStApprovers);
11918           end if;
11919         end if;
11920         if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
11921           if engStApprovers.count = 0 then
11922             fnd_log.string
11923               (fnd_log.level_statement
11924               ,'ame_engine.updateTransactionState'
11925               ,'**************** No Approvers ******************'
11926               );
11927           else
11928             for i in 1 .. engStApprovers.count loop
11929               fnd_log.string
11930                 (fnd_log.level_statement
11931                 ,'ame_engine.updateTransactionState'
11932                 ,'Approver ::: ' || engStApprovers(i).name || ' Order Number ::: ' || engStApprovers(i).approver_order_number
11933                 );
11934             end loop;
11935           end if;
11936         end if;
11937         if(updateOldApproverListIn) then
11938           updateOldApproverList;
11939         end if;
11940       end if;
11941       exception
11942         when configVarException then
11943           errorCode := -20001;
11944           errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
11945                                               messageNameIn => 'AME_400691_INV_PARAM_ENG_UPDTX');
11946           ame_util.runtimeException(packageNameIn => 'ame_engine',
11947                                     routineNameIn => 'updateTransactionState',
11948                                     exceptionNumberIn => errorCode,
11949                                     exceptionStringIn => errorMessage);
11950           raise_application_error(errorCode,
11951                                   errorMessage);
11952         when others then
11953           ame_util.runtimeException(packageNameIn => 'ame_engine',
11954                                     routineNameIn => 'updateTransactionState',
11955                                     exceptionNumberIn => sqlcode,
11956                                     exceptionStringIn => sqlerrm);
11957           raise;
11958     end updateTransactionState;
11959   procedure updateOldApproverList as
11960     tempActionTypeIds ame_util.idList;
11961     tempApiValues ame_util.charList;
11962     tempAuthorityValues ame_util.charList;
11963     tempCategories ame_util.charList;
11964     tempCount integer;
11965     tempGroupOrChainIds ame_util.idList;
11966     tempItemClasses ame_util.stringList;
11967     tempItemIds ame_util.stringList;
11968     tempNames ame_util.longStringList;
11969     tempOccurrences ame_util.idList;
11970     tempOrderNumbers ame_util.idList;
11971     tempStatuses ame_util.stringList;
11972     begin
11973       delete from ame_temp_old_approver_lists
11974         where
11975           application_id = engAmeApplicationId and
11976           transaction_id = engTransactionId;
11977       /*
11978         Bulk insert the transaction's current state into ame_temp_old_approver_lists.
11979         Take the state from engStApprovers, to account for all operations on the approver list.
11980       */
11981       ame_util.convertApproversTable2ToValues(approversTableIn => engStApprovers,
11982                                               namesOut => tempNames,
11983                                               itemClassesOut => tempItemClasses,
11984                                               itemIdsOut => tempItemIds,
11985                                               apiInsertionsOut => tempApiValues,
11986                                               authoritiesOut => tempAuthorityValues,
11987                                               actionTypeIdsOut => tempActionTypeIds,
11988                                               groupOrChainIdsOut => tempGroupOrChainIds,
11989                                               occurrencesOut => tempOccurrences,
11990                                               approverCategoriesOut => tempCategories,
11991                                               statusesOut => tempStatuses);
11992       tempCount := tempNames.count;
11993       for i in 1 .. tempCount loop
11994         if engStApprovers.exists(i) and engStApprovers(i).approver_order_number is not null then
11995            tempOrderNumbers(i) := engStApprovers(i).approver_order_number;
11996         else
11997            tempOrderNumbers(i) := i;
11998         end if;
11999       end loop;
12000       for i in 1..engStApprovers.count loop
12001         setInsertedApprovalStatus(currentApproverIndexIn => i
12002                                  ,approvalStatusIn => engStApprovers(i).approval_status);
12003       end loop;
12004       forall i in 1 .. tempCount
12005         insert into ame_temp_old_approver_lists(
12006           transaction_id,
12007           application_id,
12008           order_number,
12009           name,
12010           item_class,
12011           item_id,
12012           api_insertion,
12013           authority,
12014           action_type_id,
12015           group_or_chain_id,
12016           occurrence,
12017           approver_category,
12018           approval_status) values(
12019             engTransactionId,
12020             engAmeApplicationId,
12021             tempOrderNumbers(i),
12022             tempNames(i),
12023             tempItemClasses(i),
12024             tempItemIds(i),
12025             tempApiValues(i),
12026             tempAuthorityValues(i),
12027             tempActionTypeIds(i),
12028             tempGroupOrChainIds(i),
12029             tempOccurrences(i),
12030             tempCategories(i),
12031             tempStatuses(i));
12032       exception
12033         when others then
12034           ame_util.runtimeException(packageNameIn => 'ame_engine',
12035                                     routineNameIn => 'updateOldApproverList',
12036                                     exceptionNumberIn => sqlcode,
12037                                     exceptionStringIn => sqlerrm);
12038           raise;
12039     end updateOldApproverList;
12040   /* test procedure */
12041   procedure testEngine(printContextYNIn in varchar2 default 'N',
12042                        printAppRulesYNIn in varchar2 default 'N',
12043                        printApproversYNIn in varchar2 default 'N') as
12044     begin
12045 null;
12046       exception
12047         when others then
12048           ame_util.runtimeException(packageNameIn => 'ame_engine',
12049                                     routineNameIn => 'testEngine',
12050                                     exceptionNumberIn => sqlcode,
12051                                     exceptionStringIn => sqlerrm);
12052           raise;
12053     end testEngine;
12054   procedure updateApprovalStatus(applicationIdIn in number,
12055                                  transactionTypeIn in varchar2,
12056                                  transactionIdIn in varchar2,
12057                                  approverIn in ame_util.approverRecord2,
12058                                  notificationIn in ame_util2.notificationRecord
12059                                          default ame_util2.emptyNotificationRecord,
12060                                  forwardeeIn in ame_util.approverRecord2 default
12061                                              ame_util.emptyApproverRecord2,
12062                                  updateItemIn in boolean default false) as
12063     ameApplicationId integer;
12064     apiInsertionException exception;
12065     approver ame_util.approverRecord2;
12066     approverInIndex integer;
12067     approverInIsSpecialForwardee boolean;
12068     badApproverException exception;
12069     badForwardeeException exception;
12070     badStatusException exception;
12071     currentApprovers ame_util.approversTable2;
12072     errorCode integer;
12073     errorMessage ame_util.longStringType;
12074     firstIndexInChain integer;
12075     forwardee ame_util.approverRecord2;
12076     forwardeeIndex integer;
12077     forwardeeType ame_util.stringType;
12078     forwarderFound boolean;
12079     forwarderType ame_util.stringType;
12080     forwardingBehavior ame_util.stringType;
12081     insertedApprover ame_util.approverRecord2;
12082     prevApproverIndex integer;
12083     prevApproverOccurrence integer;
12084     repeatedIndexes ame_util.idList;
12085     repeatedAppIndexes ame_util.idList;
12086     superiorApprover ame_util.approverRecord2;
12087     tempInsertionOrder integer;
12088     tempParameter ame_temp_insertions.parameter%type;
12089     tempCOAGroupActionTypeId integer;
12090     tempPreGroupActionTypeId integer;
12091     tempPostGroupActionTypeId integer;
12092     votingRegime ame_util.charType;
12093     approverOldApprovalStatus varchar2(50);
12094     tempReason varchar2(50);
12095     tempStatus varchar2(50);
12096     begin
12097       /* Lock the transaction. */
12098       ame_engine.lockTransaction(fndApplicationIdIn => applicationIdIn,
12099                                  transactionIdIn => transactionIdIn,
12100                                  transactionTypeIdIn => transactionTypeIn);
12101       /* Clear the exception log when required. */
12102       if(approverIn.approval_status = ame_util.clearExceptionsStatus) then
12103         delete from ame_exceptions_log
12104           where
12105             transaction_id = transactionIdIn and
12106             application_id = ameApplicationId;
12107         ame_engine.unlockTransaction(fndApplicationIdIn => applicationIdIn,
12108                                      transactionIdIn => transactionIdIn,
12109                                      transactionTypeIdIn => transactionTypeIn);
12110         return;
12111       end if;
12112       /* Locate approverIn in the current approver list, if possible. */
12113       ame_engine.updateTransactionState(isTestTransactionIn => false,
12114                                         isLocalTransactionIn => false,
12115                                         fetchConfigVarsIn => true,
12116                                         fetchOldApproversIn => true,
12117                                         fetchInsertionsIn => true,
12118                                         fetchDeletionsIn => true,
12119                                         fetchAttributeValuesIn => true,
12120                                         fetchInactiveAttValuesIn => false,
12121                                         processProductionActionsIn => false,
12122                                         processProductionRulesIn => false,
12123                                         updateCurrentApproverListIn => true,
12124                                         updateOldApproverListIn => false,
12125                                         processPrioritiesIn => true,
12126                                         prepareItemDataIn => false,
12127                                         prepareRuleIdsIn => false,
12128                                         prepareRuleDescsIn => false,
12129                                         prepareApproverTreeIn => true,
12130                                         transactionIdIn => transactionIdIn,
12131                                         ameApplicationIdIn => null,
12132                                         fndApplicationIdIn => applicationIdIn,
12133                                         transactionTypeIdIn => transactionTypeIn);
12134       ame_engine.getApprovers(approversOut => currentApprovers);
12135       ame_engine.getRepeatedIndexes(repeatedIndexesOut    => repeatedIndexes
12136                                    ,repeatedAppIndexesOut => repeatedAppIndexes);
12137       ameApplicationId := ame_engine.getAmeApplicationId;
12138       approverInIndex := null;
12139       if(approverIn.occurrence is null or
12140          approverIn.group_or_chain_id is null or
12141          approverIn.action_type_id is null or
12142          approverIn.item_id is null or
12143          approverIn.item_class is null) then /* partial match */
12144         /* We need to split the search below to take in to account that the user
12145            could be trying to clear an approvers status */
12146         if(approverIn.approval_status is null) then /* Clear Approver status */
12147           for i in 1 .. currentApprovers.count loop
12148             if(approverIn.name = currentApprovers(i).name and
12149                (currentApprovers(i).approval_status = ame_util.approvedStatus or
12150                 currentApprovers(i).approval_status = ame_util.approveAndForwardStatus or
12151                 currentApprovers(i).approval_status = ame_util.forwardStatus or
12152                 currentApprovers(i).approval_status = ame_util2.reassignStatus or
12153                 currentApprovers(i).approval_status = ame_util.rejectStatus or
12154                 currentApprovers(i).approval_status = ame_util.notifiedStatus or
12155                 currentApprovers(i).approval_status = ame_util.exceptionStatus or
12156                 currentApprovers(i).approval_status = ame_util.noResponseStatus ) and
12157                (approverIn.occurrence is null or
12158                 approverIn.occurrence = currentApprovers(i).occurrence) and
12159                (approverIn.group_or_chain_id is null or
12160                 approverIn.group_or_chain_id = currentApprovers(i).group_or_chain_id) and
12161                (approverIn.action_type_id is null or
12162                 approverIn.action_type_id = currentApprovers(i).action_type_id) and
12163                (approverIn.item_id is null or
12164                 approverIn.item_id = currentApprovers(i).item_id) and
12165                (approverIn.item_class is null or
12166                 approverIn.item_class = currentApprovers(i).item_class)) then
12167               approverInIndex := i;
12168               exit;
12169             end if;
12170           end loop;
12171         else
12172           for i in 1 .. currentApprovers.count loop
12173             if(approverIn.name = currentApprovers(i).name and
12174                (currentApprovers(i).approval_status is null or
12175                 currentApprovers(i).approval_status = ame_util.nullStatus or
12176                 (currentApprovers(i).approver_category = ame_util.approvalApproverCategory and
12177                  currentApprovers(i).approval_status = ame_util.notifiedStatus)) and
12178                (approverIn.occurrence is null or
12179                 approverIn.occurrence = currentApprovers(i).occurrence) and
12180                (approverIn.group_or_chain_id is null or
12181                 approverIn.group_or_chain_id = currentApprovers(i).group_or_chain_id) and
12182                (approverIn.action_type_id is null or
12183                 approverIn.action_type_id = currentApprovers(i).action_type_id) and
12184                (approverIn.item_id is null or
12185                 approverIn.item_id = currentApprovers(i).item_id) and
12186                (approverIn.item_class is null or
12187                 approverIn.item_class = currentApprovers(i).item_class)) then
12188               approverInIndex := i;
12189               exit;
12190             end if;
12191           end loop;
12192         end if;
12193       else /* complete match */
12194         for i in 1 .. currentApprovers.count loop
12195           if(ame_engine.approversMatch(approverRecord1In => currentApprovers(i),
12196                                        approverRecord2In => approverIn)) then
12197             approverInIndex := i;
12198             exit;
12199           end if;
12200         end loop;
12201       end if;
12202       /* Initialize the local variable approver. */
12203       if(approverInIndex is null) then
12204         ame_util.copyApproverRecord2(approverRecord2In => approverIn,
12205                                      approverRecord2Out => approver);
12206       else
12207         ame_util.copyApproverRecord2(approverRecord2In => currentApprovers(approverInIndex),
12208                                      approverRecord2Out => approver);
12209         approverOldApprovalStatus := approver.approval_status;
12210         approver.approval_status := approverIn.approval_status;
12211       end if;
12212       /*
12213         Most of the remaining code should reference approver rather than approverIn or
12214         currentApprovers(approverInIndex).  Any code below this comment that cannot reference
12215         approver should have a comment explaining why.
12216       */
12217       /* Make sure the input approval statuses are valid. */
12218       if((approver.approver_category = ame_util.approvalApproverCategory and
12219           approver.approval_status not in (ame_util.approvedStatus,
12220                                            ame_util.approveAndForwardStatus,
12221                                            ame_util.forwardStatus,
12222                                            ame_util.rejectStatus,
12223                                            ame_util.noResponseStatus,
12224                                            ame_util.nullStatus,
12225                                            ame_util.notifiedStatus,
12226                                            ame_util2.reassignStatus) and
12227           approver.approval_status is not null) or
12228          (approver.approver_category = ame_util.fyiApproverCategory and
12229           approver.approval_status is not null and
12230           approver.approval_status <> ame_util.notifiedStatus)) then
12231         raise badStatusException;
12232       end if;
12233       /* Prepare forwardee (if any), if the forwarder is in the current list. */
12234       if(approver.approval_status in (ame_util.approveAndForwardStatus, ame_util.forwardStatus) and
12235          approverInIndex is not null) then
12236         /* Make sure a valid forwardee exists for forwardings. */
12237         if(forwardeeIn.name is null or
12238            forwardeeIn.name = approver.name) then
12239           raise badForwardeeException;
12240         end if;
12241         if(approver.source like (ame_util.specialForwardInsertion || '%')) then
12242           approverInIsSpecialForwardee := true;
12243         else
12244           approverInIsSpecialForwardee := false;
12245         end if;
12246         /* Copy forwardeeIn to forwardee. */
12247         ame_util.copyApproverRecord2(approverRecord2In => forwardeeIn,
12248                                      approverRecord2Out => forwardee);
12249         /* If approverInIsSpecialForwardee, silently convert api_insertion to
12250            ame_util.apiInsertion for forwardee */
12251         if approverInIsSpecialForwardee then
12252           forwardee.api_insertion := ame_util.apiInsertion;
12253         end if;
12254         /* Make sure the forwardee has the correct api_insertion value for COA forwarders. */
12255         if(/* Special forwardees can only do ad-hoc forwardings. */
12256            (approverInIsSpecialForwardee and
12257             forwardee.api_insertion <> ame_util.apiInsertion) or
12258            /* Ad-hoc approvers can only do ad-hoc forwardings. */
12259            ((not approverInIsSpecialForwardee and
12260              approver.authority <> ame_util.authorityApprover or
12261              approver.api_insertion = ame_util.apiInsertion) and
12262             forwardee.api_insertion <> ame_util.apiInsertion) or
12263            /* COA approvers other than special forwardees can only do COA forwardings. */
12264            (not approverInIsSpecialForwardee and
12265             approver.authority = ame_util.authorityApprover and
12266             approver.api_insertion <> ame_util.apiInsertion and
12267             forwardee.api_insertion <> ame_util.apiAuthorityInsertion)) then
12268           raise apiInsertionException;
12269         end if;
12270         /* Make sure forwardee has complete approver-matching data. */
12271         if(forwardee.orig_system is null or
12272            forwardee.orig_system_id is null or
12273            forwardee.display_name is null) then
12274           ame_approver_type_pkg.getOrigSystemIdAndDisplayName(nameIn =>forwardee.name,
12275                                                               origSystemOut => forwardee.orig_system,
12276                                                               origSystemIdOut => forwardee.orig_system_id,
12277                                                               displayNameOut => forwardee.display_name);
12278         end if;
12279         /*
12280           If the forwardee is from a different originating system than the forwarder,
12281           make sure the forwardee is an ad-hoc insertion.  Make this change silently,
12282           so calling applications don't have to be originating-system aware.
12283         */
12284         if(approver.orig_system <> forwardee.orig_system) then
12285           forwardee.api_insertion := ame_util.apiInsertion;
12286         end if;
12287         forwardee.item_class := approver.item_class;
12288         forwardee.item_id := approver.item_id;
12289         forwardee.authority := approver.authority;
12290         forwardee.action_type_id := approver.action_type_id;
12291         forwardee.group_or_chain_id := approver.group_or_chain_id;
12292       end if;
12293       /* Log the status update to the history table. */
12294       if(approverInIndex is null) then
12295         insert into ame_approvals_history(transaction_id,
12296                                           application_id,
12297                                           approval_status,
12298                                           row_timestamp,
12299                                           item_class,
12300                                           item_id,
12301                                           name,
12302                                           approver_category,
12303                                           action_type_id,
12304                                           group_or_chain_id,
12305                                           occurrence)
12306           values(transactionIdIn,
12307                  ameApplicationId,
12308                  decode(approver.approval_status,
12309                         ame_util.nullStatus, ame_util.nullHistoryStatus,
12310                         null, ame_util.nullHistoryStatus,
12311                         approver.approval_status),
12312                  sysdate,
12313                  approver.item_class,
12314                  approver.item_id,
12315                  approver.name,
12316                  approver.approver_category,
12317                  ame_util.nullHistoryActionTypeId,
12318                  ame_util.nullHistoryGroupOrChainId,
12319                  ame_util.nullHistoryOccurrence);
12320         /*  As approver is no longer in the approval list, log the message in the
12321             history table with a cleared date equal to sysdate. Also, first set
12322             date_cleared for  other possible rows for this approver in the history
12323             table so  that rows do not appear in the history table. */
12324         update AME_TRANS_APPROVAL_HISTORY
12325            set date_cleared = sysdate
12326           where transaction_id = transactionIdIn
12327             and application_id = ameApplicationId
12328             and name = approver.name
12329             and (approver.item_class is null or
12330                  item_class = approver.item_class)
12331             and (approver.item_id is null or
12332                  item_id = approver.item_id)
12333             and (approver.action_type_id is null or
12334                  action_type_id = approver.action_type_id)
12335             and (approver.group_or_chain_id is null or
12336                  group_or_chain_id = approver.group_or_chain_id)
12337             and (approver.occurrence is null or
12338                  occurrence = approver.occurrence)
12339             and date_cleared is null;
12340       /* Log the approvers response in the Notification Approval History table before
12341          doing any further processing */
12342         insertIntoTransApprovalHistory
12343           (transactionIdIn         => transactionIdIn
12344           ,applicationIdIn         => ameApplicationId
12345           ,orderNumberIn           => approver.approver_order_number
12346           ,nameIn                  => approver.name
12347           ,appCategoryIn           => approver.approver_category
12348           ,itemClassIn             => approver.item_class
12349           ,itemIdIn                => approver.item_id
12350           ,actionTypeIdIn          => ame_util.nullHistoryActionTypeId
12351           ,authorityIn             => approver.authority
12352           ,statusIn                => approver.approval_status
12353           ,grpOrChainIdIn          => ame_util.nullHistoryGroupOrChainId
12354           ,occurrenceIn            => ame_util.nullHistoryOccurrence
12355           ,apiInsertionIn          => approver.api_insertion
12356           ,memberOrderNumberIn     => approver.member_order_number
12357           ,notificationIdIn        => notificationIn.notification_id
12358           ,userCommentsIn          => notificationIn.user_comments
12359           ,dateClearedIn           => sysdate
12360           ,historyTypeIn           => 'APPROVERNOTPRESENT');
12361         /* Insert a warning into AME's exception log and return. */
12362         errorCode := -20001;
12363         errorMessage := ame_util.getMessage(applicationShortNameIn => 'PER',
12364                                             messageNameIn => 'AME_400065_API_NO_MATCH_APPR2');
12365         /*
12366           Pass localErrorIn => true in this case, because we're just logging a warning
12367           to the AME exception log, and we don't want the warning to appear in the
12368           Workflow context stack.
12369         */
12370         ame_util.runtimeException(packageNameIn => 'ame_engine',
12371                                   routineNameIn => 'updateApprovalStatus',
12372                                   exceptionNumberIn => errorCode,
12373                                   exceptionStringIn => errorMessage);
12374         return;
12375       end if;
12376       insert into ame_approvals_history(transaction_id,
12377                                         application_id,
12378                                         approval_status,
12379                                         row_timestamp,
12380                                         item_class,
12381                                         item_id,
12382                                         name,
12383                                         approver_category,
12384                                         action_type_id,
12385                                         group_or_chain_id,
12386                                         occurrence)
12387         values(transactionIdIn,
12388                ameApplicationId,
12389                decode(approver.approval_status,
12390                       ame_util.nullStatus, ame_util.nullHistoryStatus,
12391                       null, ame_util.nullHistoryStatus,
12392                       approver.approval_status),
12393                sysdate,
12394                approver.item_class,
12395                approver.item_id,
12396                approver.name,
12397                approver.approver_category,
12398                approver.action_type_id,
12399                approver.group_or_chain_id,
12400                approver.occurrence);
12401       /*
12402         If the approver has been suppressed or is a repeated approver, disregard their response,
12403         even if they're trying to forward.
12404       */
12405       if(approverOldApprovalStatus in (ame_util.suppressedStatus, ame_util.beatByFirstResponderStatus, ame_util.repeatedStatus)) then
12406         /* The response though disregarded must be logged in the history table. This should not be shown in
12407            the history region. Hence set the date_cleared to sysdate. */
12408         insertIntoTransApprovalHistory
12409           (transactionIdIn         => transactionIdIn
12410           ,applicationIdIn         => ameApplicationId
12411           ,orderNumberIn           => approver.approver_order_number
12412           ,nameIn                  => approver.name
12413           ,appCategoryIn           => approver.approver_category
12414           ,itemClassIn             => approver.item_class
12415           ,itemIdIn                => approver.item_id
12416           ,actionTypeIdIn          => approver.action_type_id
12417           ,authorityIn             => approver.authority
12418           ,statusIn                => approver.approval_status
12419           ,grpOrChainIdIn          => approver.group_or_chain_id
12420           ,occurrenceIn            => approver.occurrence
12421           ,apiInsertionIn          => approver.api_insertion
12422           ,memberOrderNumberIn     => approver.member_order_number
12423           ,notificationIdIn        => notificationIn.notification_id
12424           ,userCommentsIn          => notificationIn.user_comments
12425           ,dateClearedIn           => sysdate
12426           ,historyTypeIn           => 'APPROVERPRESENT');
12427         return;
12428       end if;
12429       /* Log the approvers response in the Notification Approval History table before
12430          doing any further processing */
12431         insertIntoTransApprovalHistory
12432           (transactionIdIn         => transactionIdIn
12433           ,applicationIdIn         => ameApplicationId
12434           ,orderNumberIn           => approver.approver_order_number
12435           ,nameIn                  => approver.name
12436           ,appCategoryIn           => approver.approver_category
12437           ,itemClassIn             => approver.item_class
12438           ,itemIdIn                => approver.item_id
12439           ,actionTypeIdIn          => approver.action_type_id
12440           ,authorityIn             => approver.authority
12441           ,statusIn                => approver.approval_status
12442           ,grpOrChainIdIn          => approver.group_or_chain_id
12443           ,occurrenceIn            => approver.occurrence
12444           ,apiInsertionIn          => approver.api_insertion
12445           ,memberOrderNumberIn     => approver.member_order_number
12446           ,notificationIdIn        => notificationIn.notification_id
12447           ,userCommentsIn          => notificationIn.user_comments
12448           ,dateClearedIn           => null
12449           ,historyTypeIn           => 'APPROVERPRESENT');
12450       /*
12451         Update the status of approverIn in ame_temp_old_approver_lists.  If updateItemIn
12452         is true, update also any other occurrences of the same approver for the same item
12453         class and item ID.
12454       */
12455       if(updateItemIn) then
12456         if(approver.approval_status in (ame_util.forwardStatus, ame_util.approveAndForwardStatus)) then
12457           /* Update the forwarder proper. */
12458           update ame_temp_old_approver_lists
12459             set approval_status = approver.approval_status
12460             where
12461               application_id = ameApplicationId and
12462               transaction_id = transactionIdIn and
12463               name = approver.name and
12464               item_class = approver.item_class and
12465               item_id = approver.item_id and
12466               action_type_id = approver.action_type_id and
12467               group_or_chain_id = approver.group_or_chain_id and
12468               occurrence = approver.occurrence;
12469           /* Suppress other occurrences of the approver, for the same item. */
12470           update ame_temp_old_approver_lists
12471             set approval_status = ame_util.suppressedStatus
12472             where
12473               application_id = ameApplicationId and
12474               transaction_id = transactionIdIn and
12475               name = approver.name and
12476               item_class = approver.item_class and
12477               item_id = approver.item_id and
12478               (action_type_id <> approver.action_type_id or
12479                group_or_chain_id <> approver.group_or_chain_id or
12480                occurrence <> approver.occurrence);
12481         else
12482           update ame_temp_old_approver_lists
12483             set approval_status = approver.approval_status
12484             where
12485               application_id = ameApplicationId and
12486               transaction_id = transactionIdIn and
12487               name = approver.name and
12488               item_class = approver.item_class and
12489               item_id = approver.item_id;
12490         end if;
12491       else
12492         update ame_temp_old_approver_lists
12493           set approval_status = approver.approval_status
12494           where
12495             application_id = ameApplicationId and
12496             transaction_id = transactionIdIn and
12497             name = approver.name and
12498             item_class = approver.item_class and
12499             item_id = approver.item_id and
12500             action_type_id = approver.action_type_id and
12501             group_or_chain_id = approver.group_or_chain_id and
12502             occurrence = approver.occurrence;
12503       end if;
12504       --+
12505       if approverInIndex is not null then
12506         setInsertedApprovalStatus(currentApproverIndexIn => approverInIndex
12507                                   ,approvalStatusIn => approver.approval_status);
12508       end if;
12509       if approver.approval_status in (ame_util.approvedStatus
12510                                      ,ame_util.rejectStatus
12511                                      ,ame_util.approveAndForwardStatus
12512                                      ,ame_util.forwardStatus
12513                                      ,ame_util.noResponseStatus) then
12514         for z in 1 .. repeatedIndexes.count loop
12515           if repeatedIndexes(z) = approverInIndex and repeatedAppIndexes(z) <> approverInIndex then
12516             update ame_temp_old_approver_lists
12517                set approval_status = decode(approver.approval_status
12518                                            ,ame_util.approvedStatus
12519                                            ,ame_util.approvedByRepeatedStatus
12520                                            ,ame_util.approveAndForwardStatus
12521                                            ,ame_util.approvedByRepeatedStatus
12522                                            ,ame_util.rejectStatus
12523                                            ,ame_util.rejectedByRepeatedStatus
12524                                            ,ame_util.forwardStatus
12525                                            ,ame_util2.forwardByRepeatedStatus
12526                                            ,ame_util2.reassignStatus
12527                                            ,ame_util.nullStatus
12528                                            ,ame_util.noResponseStatus
12529                                            ,ame_util2.noResponseByRepeatedStatus
12530                                            ,ame_util.repeatedStatus)
12531              where application_id = ameApplicationId
12532                and transaction_id = transactionIdIn
12533                and name           = approver.name
12534                and item_class        = currentApprovers(repeatedAppIndexes(z)).item_class
12535                and item_id           = currentApprovers(repeatedAppIndexes(z)).item_id
12536                and action_type_id    = currentApprovers(repeatedAppIndexes(z)).action_type_id
12537                and group_or_chain_id = currentApprovers(repeatedAppIndexes(z)).group_or_chain_id
12538                and occurrence        = currentApprovers(repeatedAppIndexes(z)).occurrence
12539                and approval_status in ( ame_util.notifiedByRepeatedStatus
12540                                        ,ame_util.repeatedStatus);
12541             select decode(approver.approval_status
12542                                            ,ame_util.approvedStatus
12543                                            ,ame_util.approvedByRepeatedStatus
12544                                            ,ame_util.approveAndForwardStatus
12545                                            ,ame_util.approvedByRepeatedStatus
12546                                            ,ame_util.rejectStatus
12547                                            ,ame_util.rejectedByRepeatedStatus
12548                                            ,ame_util.forwardStatus
12549                                            ,ame_util2.forwardByRepeatedStatus
12550                                            ,ame_util2.reassignStatus
12551                                            ,ame_util.nullStatus
12552                                            ,ame_util.noResponseStatus
12553                                            ,ame_util2.noResponseByRepeatedStatus
12554                                            ,ame_util.repeatedStatus) into tempStatus from dual;
12555             setInsertedApprovalStatus(currentApproverIndexIn => repeatedAppIndexes(z)
12556                                      ,approvalStatusIn => tempStatus);
12557           end if;
12558         end loop;
12559       end if;
12560       if approver.approval_status in (ame_util.approvedStatus, ame_util.rejectStatus ) then
12561       /* Account for approval-group and chain-of-authority voting. */
12562       /* get action type id's  for  ame_util.groupChainApprovalTypeName,
12563          ame_util.postApprovalTypeName and ame_util.preApprovalTypeName */
12564       tempCOAGroupActionTypeId := ame_action_pkg.getActionTypeIdByName(actionTypeNameIn =>
12565                                          ame_util.groupChainApprovalTypeName);
12566       tempPreGroupActionTypeId := ame_action_pkg.getActionTypeIdByName(actionTypeNameIn =>
12567                                          ame_util.preApprovalTypeName);
12568       tempPostGroupActionTypeId := ame_action_pkg.getActionTypeIdByName(actionTypeNameIn =>
12569                                          ame_util.postApprovalTypeName);
12570         if approver.action_type_id in (tempPreGroupActionTypeId
12571                                       ,tempPostGroupActionTypeId) then
12572                  -- removed tempCOAGroupActionTypeId from above list for the
12573                  -- bug 4095605
12574         votingRegime := ame_approval_group_pkg.getVotingRegime(
12575                            approvalGroupIdIn => approver.group_or_chain_id ,
12576                            applicationIdIn => ameApplicationId);
12577                                -- in approver.group_or_chain_id
12578       else
12579         votingRegime := ame_engine.getActionTypeVotingRegime(actionTypeIdIn => approver.action_type_id);
12580       end if;
12581       if(votingRegime = ame_util.firstApproverVoting) then
12582         /*
12583           approverIn must be the first responder (otherwise, they would be suppressed,
12584           and we would have returned above).  Suppress the other approval approvers in the
12585           group or chain (including other occurrences of the input approver).
12586         */
12587         update ame_temp_old_approver_lists
12588           set approval_status = ame_util.beatByFirstResponderStatus
12589           where
12590             application_id = ameApplicationId and
12591             transaction_id = transactionIdIn and
12592             (name <> approver.name or
12593              occurrence <> approver.occurrence) and
12594             item_class = approver.item_class and
12595             item_id = approver.item_id and
12596             action_type_id = approver.action_type_id and
12597             group_or_chain_id = approver.group_or_chain_id and
12598               approver_category = ame_util.approvalApproverCategory and
12599               approval_status = ame_util.notifiedStatus;
12600         for i in 1..currentApprovers.count loop
12601           if currentApprovers(i).item_class = approver.item_class and
12602           currentApprovers(i).item_id = approver.item_id and
12603           currentApprovers(i).action_type_id = approver.action_type_id and
12604           currentApprovers(i).group_or_chain_id = approver.group_or_chain_id and
12605           currentApprovers(i).approver_category = approver.approver_category and
12606           currentApprovers(i).approval_status = ame_util.notifiedStatus and
12607           (currentApprovers(i).name <> approver.name or
12608           currentApprovers(i).occurrence <>  approver.occurrence) then
12609             setInsertedApprovalStatus(currentApproverIndexIn => i
12610                                   ,approvalStatusIn => ame_util.beatByFirstResponderStatus);
12611           end if;
12612         end loop;
12613         /* Insert rows in the notification approval history region for approvers
12614            with beat by first responder */
12615         insertIntoTransApprovalHistory
12616           (transactionIdIn         => transactionIdIn
12617           ,applicationIdIn         => ameApplicationId
12618           ,orderNumberIn           => approver.approver_order_number
12619           ,nameIn                  => approver.name
12620           ,appCategoryIn           => null
12621           ,itemClassIn             => approver.item_class
12622           ,itemIdIn                => approver.item_id
12623           ,actionTypeIdIn          => approver.action_type_id
12624           ,authorityIn             => null
12625           ,statusIn                => null
12626           ,grpOrChainIdIn          => approver.group_or_chain_id
12627           ,occurrenceIn            => approver.occurrence
12628           ,apiInsertionIn          => approver.api_insertion
12629           ,memberOrderNumberIn     => approver.member_order_number
12630           ,notificationIdIn        => notificationIn.notification_id
12631           ,userCommentsIn          => null
12632           ,dateClearedIn           => null
12633           ,historyTypeIn           => 'BEATBYFIRSTRESPONDER');
12634           --+
12635           for x in 1 .. currentApprovers.count loop
12636             if currentApprovers(x).item_class = approver.item_class
12637               and currentApprovers(x).item_id = approver.item_id
12638               and currentApprovers(x).action_type_id = approver.action_type_id
12639               and currentApprovers(x).group_or_chain_id = approver.group_or_chain_id
12640               and (currentApprovers(x).name <> approver.name or
12641                    currentApprovers(x).occurrence <> approver.occurrence)
12642               and currentApprovers(x).approver_category = ame_util.approvalApproverCategory
12643               and currentApprovers(x).approval_status <> ame_util.approvedByRepeatedStatus then
12644               for z in 1 .. repeatedIndexes.count loop
12645                 if repeatedIndexes(z) = x and repeatedAppIndexes(z) <> x then
12646                   update ame_temp_old_approver_lists
12647                      set approval_status = ame_util.nullStatus
12648                    where application_id = ameApplicationId
12649                      and transaction_id = transactionIdIn
12650                      and name           = currentApprovers(x).name
12651                      and item_class        = currentApprovers(repeatedAppIndexes(z)).item_class
12652                      and item_id           = currentApprovers(repeatedAppIndexes(z)).item_id
12653                      and action_type_id    = currentApprovers(repeatedAppIndexes(z)).action_type_id
12654                      and group_or_chain_id = currentApprovers(repeatedAppIndexes(z)).group_or_chain_id
12655                      and occurrence        = currentApprovers(repeatedAppIndexes(z)).occurrence
12656                      and approval_status   = ame_util.notifiedByRepeatedStatus;
12657                   if(sql%rowcount > 0) then
12658                        setInsertedApprovalStatus(currentApproverIndexIn => repeatedAppIndexes(z)
12659                                   ,approvalStatusIn => ame_util.nullStatus);
12660                   end if;
12661                 end if;
12662               end loop;
12663             end if;
12664           end loop;
12665           --+
12666         end if;
12667       end if;
12668       --+
12669       --+ process reassignStatus
12670       --+
12671       if(approver.approval_status = ame_util2.reassignStatus) then
12672         ame_util.copyApproverRecord2(approverRecord2In => forwardeeIn,
12673                                      approverRecord2Out => forwardee);
12674         -- fetch forwardee details
12675         if(forwardee.orig_system is null or
12676            forwardee.orig_system_id is null or
12677            forwardee.display_name is null) then
12678           ame_approver_type_pkg.getOrigSystemIdAndDisplayName(nameIn =>forwardee.name,
12679                                                               origSystemOut => forwardee.orig_system,
12680                                                               origSystemIdOut => forwardee.orig_system_id,
12681                                                               displayNameOut => forwardee.display_name);
12682         end if;
12683           tempInsertionOrder := ame_engine.getNextInsertionOrder;
12684           tempParameter := approver.name ||
12685                            ame_util.fieldDelimiter ||
12686                            approver.item_class ||
12687                            ame_util.fieldDelimiter ||
12688                            approver.item_id ||
12689                            ame_util.fieldDelimiter ||
12690                            approver.action_type_id ||
12691                            ame_util.fieldDelimiter ||
12692                            approver.group_or_chain_id ||
12693                            ame_util.fieldDelimiter ||
12694                            approver.occurrence;
12695           insert into ame_temp_insertions(
12696               transaction_id,
12697               application_id,
12698               insertion_order,
12699               order_type,
12700               parameter,
12701               description,
12702               name,
12703               item_class,
12704               item_id,
12705               approver_category,
12706               api_insertion,
12707               authority,
12708               effective_date,
12709               reason) values(
12710                 transactionIdIn,
12711                 ameApplicationId,
12712                 tempInsertionOrder,
12713                 ame_util.afterApprover,
12714                 tempParameter,
12715                 ame_util.afterApproverDescription || approver.display_name,
12716                 forwardee.name,
12717                 forwardee.item_class,
12718                 forwardee.item_id,
12719                 forwardee.approver_category,
12720                 decode(forwarderType,
12721                        ame_util.chainOfAuthorityForwarder, ame_util.apiAuthorityInsertion,
12722                        ame_util.apiInsertion),
12723                 approver.authority,
12724                 sysdate,
12725                 ame_approver_deviation_pkg.reassignStatus );
12726       end if;
12727       --+
12728       /* Process the forwardee, checking for special forwarding cases. */
12729       if(approver.approval_status in (ame_util.forwardStatus,
12730                                         ame_util.approveAndForwardStatus)) then
12731         forwardeeType := null;
12732         if(approverInIsSpecialForwardee or
12733            approver.authority <> ame_util.authorityApprover or
12734            approver.api_insertion = ame_util.apiInsertion) then
12735           forwarderType := ame_util.adHocForwarder;
12736         else
12737           forwarderType := ame_util.chainOfAuthorityForwarder;
12738         end if;
12739         /* Use the reverse keyword to find the match nearest to approver. */
12740         for i in reverse 1 .. approverInIndex loop
12741           if(currentApprovers(i).name = forwardee.name) then
12742             forwardeeIndex := i;
12743             if(forwarderType = ame_util.chainOfAuthorityForwarder and
12744                currentApprovers(i).action_type_id = forwardee.action_type_id and
12745                currentApprovers(i).group_or_chain_id = forwardee.group_or_chain_id) then
12746               forwardeeType := ame_util.previousSameChainForwardee;
12747             else
12748               forwardeeType := ame_util.alreadyInListForwardee;
12749             end if;
12750             exit;
12751           end if;
12752         end loop;
12753         if(forwarderType = ame_util.chainOfAuthorityForwarder and
12754            (forwardeeType is null or
12755             forwardeeType = ame_util.alreadyInListForwardee) and
12756            ame_approver_type_pkg.isASubordinate(approverIn => approver,
12757                                                 possibleSubordApproverIn => forwardee)) then
12758           forwardeeType := ame_util.subordSameHierarchyForwardee;
12759         end if;
12760         if(forwardeeType = ame_util.previousSameChainForwardee) then
12761           forwardee.occurrence := currentApprovers(forwardeeIndex).occurrence + 1;
12762         else
12763           forwardee.occurrence := 1;
12764         end if;
12765         if(forwardeeType is null) then /* Handle normal forwarding cases. */
12766           if(approver.orig_system <> forwardee.orig_system) then
12767             forwarderType := ame_util.adHocForwarder;
12768           end if;
12769           tempInsertionOrder := ame_engine.getNextInsertionOrder;
12770           tempParameter := approver.name ||
12771                            ame_util.fieldDelimiter ||
12772                            approver.item_class ||
12773                            ame_util.fieldDelimiter ||
12774                            approver.item_id ||
12775                            ame_util.fieldDelimiter ||
12776                            approver.action_type_id ||
12777                            ame_util.fieldDelimiter ||
12778                            approver.group_or_chain_id ||
12779                            ame_util.fieldDelimiter ||
12780                            approver.occurrence;
12781           insert into ame_temp_insertions(
12782               transaction_id,
12783               application_id,
12784               insertion_order,
12785               order_type,
12786               parameter,
12787               description,
12788               name,
12789               item_class,
12790               item_id,
12791               approver_category,
12792               api_insertion,
12793               authority,
12794               effective_date,
12795               reason) values(
12796                 transactionIdIn,
12797                 ameApplicationId,
12798                 tempInsertionOrder,
12799                 ame_util.afterApprover,
12800                 tempParameter,
12801                 ame_util.afterApproverDescription || approver.display_name,
12802                 forwardee.name,
12803                 forwardee.item_class,
12804                 forwardee.item_id,
12805                 forwardee.approver_category,
12806                 decode(forwarderType,
12807                        ame_util.chainOfAuthorityForwarder, ame_util.apiAuthorityInsertion,
12808                        ame_util.apiInsertion),
12809                 approver.authority,
12810                 sysdate
12811                 ,ame_approver_deviation_pkg.forwardReason );
12812         else /* Handle special forwarding cases. */
12813           /*
12814             All of the insertees generated within this if statement should have the same
12815             action_type_id and group_or_chain_id as approver.  The insertees' source
12816             should always be ame_util.specialForwardInsertion.  The insertions' order
12817             types should always be ame_util.afterApprover.
12818           */
12819           forwardingBehavior := ame_engine.getForwardingBehavior(forwarderTypeIn => forwarderType,
12820                                                                  forwardeeTypeIn => forwardeeType,
12821                                                                  approvalStatusIn => approver.approval_status);
12822           if(forwardingBehavior in (ame_util.repeatForwarder,
12823                                     ame_util.skipForwarder,
12824                                     ame_util.remand)) then
12825             /*
12826               Locate the start of the chain, so we can calculate each insertee's occurrence
12827               value, for use in the following insertee's insertion parameter.
12828             */
12829             for i in reverse 1 .. (approverInIndex - 1) loop
12830               if(currentApprovers(i).group_or_chain_id <> approver.group_or_chain_id or
12831                  currentApprovers(i).action_type_id <> approver.action_type_id or
12832                  currentApprovers(i).item_id <> approver.item_id or
12833                  currentApprovers(i).item_class <> approver.item_class) then
12834                 firstIndexInChain := i + 1;
12835                 exit;
12836               end if;
12837             end loop;
12838             if(firstIndexInChain is null) then
12839               firstIndexInChain := 1;
12840             end if;
12841           end if;
12842           /* Handle the special forwarding cases. */
12843           if(forwardingBehavior in (ame_util.forwardeeOnly,
12844                                     ame_util.forwarderAndForwardee)) then
12845             /* Insert forwardee as ad-hoc or COA, according to whether approverIn is ad-hoc or COA. */
12846             tempInsertionOrder := ame_engine.getNextInsertionOrder;
12847             tempParameter := approver.name ||
12848                              ame_util.fieldDelimiter ||
12849                              approver.item_class ||
12850                              ame_util.fieldDelimiter ||
12851                              approver.item_id ||
12852                              ame_util.fieldDelimiter ||
12853                              approver.action_type_id ||
12854                              ame_util.fieldDelimiter ||
12855                              approver.group_or_chain_id ||
12856                              ame_util.fieldDelimiter ||
12857                              approver.occurrence;
12858             insert into ame_temp_insertions(
12859               transaction_id,
12860               application_id,
12861               insertion_order,
12862               order_type,
12863               parameter,
12864               description,
12865               name,
12866               item_class,
12867               item_id,
12868               approver_category,
12869               api_insertion,
12870               authority,
12871               special_forwardee,
12872               effective_date,
12873               reason) values(
12874                 transactionIdIn,
12875                 ameApplicationId,
12876                 tempInsertionOrder,
12877                 ame_util.afterApprover,
12878                 tempParameter,
12879                 ame_util.afterApproverDescription || approver.display_name,
12880                 forwardee.name,
12881                 forwardee.item_class,
12882                 forwardee.item_id,
12883                 ame_util.approvalApproverCategory, /* Forwarding is not possible from an FYI approver. */
12884                 decode(forwarderType,
12885                        ame_util.chainOfAuthorityForwarder, ame_util.apiAuthorityInsertion,
12886                        ame_util.apiInsertion),
12887                 approver.authority,
12888                 ame_util.booleanTrue,
12889                 sysdate,
12890                 ame_approver_deviation_pkg.forwardReason);
12891             if(forwardingBehavior = ame_util.forwarderAndForwardee) then /* Insert the forwarder. */
12892               tempInsertionOrder := ame_engine.getNextInsertionOrder;
12893               tempParameter := forwardee.name ||
12894                                ame_util.fieldDelimiter ||
12895                                forwardee.item_class ||
12896                                ame_util.fieldDelimiter ||
12897                                forwardee.item_id ||
12898                                ame_util.fieldDelimiter ||
12899                                forwardee.action_type_id ||
12900                                ame_util.fieldDelimiter ||
12901                                forwardee.group_or_chain_id ||
12902                                ame_util.fieldDelimiter ||
12903                                forwardee.occurrence;
12904               insert into ame_temp_insertions(
12905                 transaction_id,
12906                 application_id,
12907                 insertion_order,
12908                 order_type,
12909                 parameter,
12910                 description,
12911                 name,
12912                 item_class,
12913                 item_id,
12914                 approver_category,
12915                 api_insertion,
12916                 authority,
12917                 special_forwardee,
12918                 effective_date,
12919                 reason) values(
12920                   transactionIdIn,
12921                   ameApplicationId,
12922                   tempInsertionOrder,
12923                   ame_util.afterApprover,
12924                   tempParameter,
12925                   ame_util.afterApproverDescription || forwardee.display_name,
12926                   approver.name,
12927                   approver.item_class,
12928                   approver.item_id,
12929                   ame_util.approvalApproverCategory, /* Forwarding is not possible from an FYI approver. */
12930                   decode(forwarderType,
12931                          ame_util.chainOfAuthorityForwarder, ame_util.apiAuthorityInsertion,
12932                          ame_util.apiInsertion),
12933                   approver.authority,
12934                   ame_util.booleanTrue,
12935                   sysdate,
12936                   ame_approver_deviation_pkg.forwardForwardeeReason);
12937             end if;
12938           elsif(forwardingBehavior in (ame_util.repeatForwarder, ame_util.skipForwarder)) then
12939             /*
12940               These cases are for a forwardee who is a subordinate of approverIn (who must be
12941               a COA approver), but who does not already precede approverIn in the list.  In this
12942               case we insert starting at the insertee, and ascending the hierarchy up to but not
12943               including approver.  In the case of ame_util.repeatForwarder, we then add
12944               approverIn and stop.  In the case of ame_util.skipForwarder, we then add
12945               approverIn's superior and stop.  The insertees are all COA approvers.
12946             */
12947             /* Insert the forwardee. */
12948             tempInsertionOrder := ame_engine.getNextInsertionOrder;
12949             tempParameter := approver.name ||
12950                              ame_util.fieldDelimiter ||
12951                              approver.item_class ||
12952                              ame_util.fieldDelimiter ||
12953                              approver.item_id ||
12954                              ame_util.fieldDelimiter ||
12955                              approver.action_type_id ||
12956                              ame_util.fieldDelimiter ||
12957                              approver.group_or_chain_id ||
12958                              ame_util.fieldDelimiter ||
12959                              approver.occurrence;
12960             insert into ame_temp_insertions(
12961               transaction_id,
12962               application_id,
12963               insertion_order,
12964               order_type,
12965               parameter,
12966               description,
12967               name,
12968               item_class,
12969               item_id,
12970               approver_category,
12971               api_insertion,
12972               authority,
12973               special_forwardee,
12974               effective_date,
12975               reason) values(
12976                 transactionIdIn,
12977                 ameApplicationId,
12978                 tempInsertionOrder,
12979                 ame_util.afterApprover,
12980                 tempParameter,
12981                 ame_util.afterApproverDescription || approver.display_name,
12982                 forwardee.name,
12983                 forwardee.item_class,
12984                 forwardee.item_id,
12985                 ame_util.approvalApproverCategory, /* Forwarding is not possible from an FYI approver. */
12986                 ame_util.apiAuthorityInsertion,
12987                 ame_util.authorityApprover,
12988                 ame_util.booleanTrue,
12989                 sysdate,
12990                 ame_approver_deviation_pkg.forwardReason);
12991             insertedApprover.name := forwardee.name;
12992             insertedApprover.orig_system := forwardee.orig_system;
12993             insertedApprover.orig_system_id := forwardee.orig_system_id;
12994             insertedApprover.item_class := forwardee.item_class;
12995             insertedApprover.item_id := forwardee.item_id;
12996             insertedApprover.action_type_id := forwardee.action_type_id;
12997             insertedApprover.group_or_chain_id :=forwardee.group_or_chain_id;
12998             insertedApprover.occurrence := forwardee.occurrence;
12999             forwarderFound := false;
13000             /* Iterate through the forwardee's chain of authority. */
13001             loop
13002               /* Get the next superior to insert. */
13003               tempReason := ame_approver_deviation_pkg.forwardEngInsReason;
13004               ame_approver_type_pkg.getSuperior(approverIn => insertedApprover,
13005                                                 superiorOut => superiorApprover);
13006               if(superiorApprover.name = approver.name) then
13007                 forwarderFound := true;
13008                 tempReason := ame_approver_deviation_pkg.forwardForwardeeReason;
13009                 if(forwardingBehavior = ame_util.skipForwarder) then
13010                   tempReason := ame_approver_deviation_pkg.forwardEngInsReason;
13011                   --insertedApprover.name := approver.name;
13012                   --insertedApprover.orig_system_id := approver.orig_system_id;
13013                   ame_approver_type_pkg.getSuperior(approverIn => approver,
13014                                                     superiorOut => superiorApprover);
13015                 end if;
13016               end if;
13017               /* Calculate insertedApprover.occurrence. */
13018               insertedApprover.occurrence := 1;
13019               for i in reverse firstIndexInChain .. approverInIndex loop
13020                 if(currentApprovers(i).name = insertedApprover.name) then
13021                   insertedApprover.occurrence := currentApprovers(i).occurrence + 1;
13022                   exit;
13023                 end if;
13024               end loop;
13025               /* Prepare and do the insertion. */
13026               tempInsertionOrder := ame_engine.getNextInsertionOrder;
13027               tempParameter := insertedApprover.name ||
13028                                ame_util.fieldDelimiter ||
13029                                insertedApprover.item_class ||
13030                                ame_util.fieldDelimiter ||
13031                                insertedApprover.item_id ||
13032                                ame_util.fieldDelimiter ||
13033                                insertedApprover.action_type_id ||
13034                                ame_util.fieldDelimiter ||
13035                                insertedApprover.group_or_chain_id ||
13036                                ame_util.fieldDelimiter ||
13037                                insertedApprover.occurrence;
13038               insert into ame_temp_insertions(
13039                 transaction_id,
13040                 application_id,
13041                 insertion_order,
13042                 order_type,
13043                 parameter,
13044                 description,
13045                 name,
13046                 item_class,
13047                 item_id,
13048                 approver_category,
13049                 api_insertion,
13050                 authority,
13051                 special_forwardee,
13052                 effective_date,
13053                 reason) values(
13054                   transactionIdIn,
13055                   ameApplicationId,
13056                   tempInsertionOrder,
13057                   ame_util.afterApprover,
13058                   tempParameter,
13059                   ame_util.afterApproverDescription || insertedApprover.display_name,
13060                   superiorApprover.name,
13061                   approver.item_class,
13062                   approver.item_id,
13063                   ame_util.approvalApproverCategory, /* Forwarding is not possible from an FYI approver. */
13064                   ame_util.apiAuthorityInsertion,
13065                   ame_util.authorityApprover,
13066                   ame_util.booleanTrue,
13067                   sysdate,
13068                   tempReason);
13069               if(forwarderFound) then
13070                 exit;
13071               end if;
13072               insertedApprover.name := superiorApprover.name;
13073               insertedApprover.orig_system_id := superiorApprover.orig_system_id;
13074             end loop;
13075           elsif(forwardingBehavior = ame_util.remand) then
13076             /*
13077               Remanding is possible only when forwardeeIn already precedes approverIn in
13078               the list (not necessarily in the same chain), and approverIn is a COA approver.  In
13079               such cases, we insert starting with forwardeeIn and continuing up to and including
13080               approver.  The insertees are always ad-hoc, and pertain to the same item, sublist,
13081               action type, and group or chain as the forwarder.
13082             */
13083             for i in forwardeeIndex .. approverInIndex loop
13084               if(i = forwardeeIndex) then
13085                 prevApproverIndex := approverInIndex;
13086                 prevApproverOccurrence := approver.occurrence;
13087               else
13088                 prevApproverIndex := i - 1;
13089                 prevApproverOccurrence := 1;
13090                 for i in reverse firstIndexInChain .. approverInIndex loop
13091                   if(currentApprovers(i).name = currentApprovers(prevApproverIndex).name) then
13092                     prevApproverOccurrence := currentApprovers(prevApproverIndex).occurrence + 1;
13093                     exit;
13094                   end if;
13095                 end loop;
13096               end if;
13097               tempInsertionOrder := ame_engine.getNextInsertionOrder;
13098               tempParameter := currentApprovers(prevApproverIndex).name ||
13099                                ame_util.fieldDelimiter ||
13100                                approver.item_class ||
13101                                ame_util.fieldDelimiter ||
13102                                approver.item_id ||
13103                                ame_util.fieldDelimiter ||
13104                                approver.action_type_id ||
13105                                ame_util.fieldDelimiter ||
13106                                approver.group_or_chain_id ||
13107                                ame_util.fieldDelimiter ||
13108                                prevApproverOccurrence;
13109               insert into ame_temp_insertions(
13110                 transaction_id,
13111                 application_id,
13112                 insertion_order,
13113                 order_type,
13114                 parameter,
13115                 description,
13116                 name,
13117                 item_class,
13118                 item_id,
13119                 approver_category,
13120                 api_insertion,
13121                 authority,
13122                 special_forwardee,
13123                 effective_date,
13124                 reason) values(
13125                   transactionIdIn,
13126                   ameApplicationId,
13127                   tempInsertionOrder,
13128                   ame_util.afterApprover,
13129                   tempParameter,
13130                   ame_util.afterApproverDescription || insertedApprover.display_name,
13131                   currentApprovers(i).name,
13132                   approver.item_class,
13133                   approver.item_id,
13134                   ame_util.approvalApproverCategory, /* Forwarding is not possible from an FYI approver. */
13135                   ame_util.apiInsertion,
13136                   approver.authority,
13137                   ame_util.booleanTrue,
13138                   sysdate,
13139                   ame_approver_deviation_pkg.forwardRemandReason);
13140               prevApproverIndex := prevApproverIndex + 1;
13141             end loop;
13142           /* else forwardingBehavior = ame_util.ignoreForwarding */
13143         end if;
13144       end if;
13145       /* Cycle the engine to write the forwardees out to the old-approvers table. */
13146       ame_engine.updateTransactionState(isTestTransactionIn => false,
13147                                           isLocalTransactionIn => false,
13148                                           fetchConfigVarsIn => true,
13149                                           fetchOldApproversIn => true,
13150                                           fetchInsertionsIn => true,
13151                                           fetchDeletionsIn => true,
13152                                           fetchAttributeValuesIn => true,
13153                                           fetchInactiveAttValuesIn => false,
13154                                           processProductionActionsIn => false,
13155                                           processProductionRulesIn => false,
13156                                           updateCurrentApproverListIn => true,
13157                                           updateOldApproverListIn => true,
13158                                           processPrioritiesIn => true,
13159                                           prepareItemDataIn => false,
13160                                           prepareRuleIdsIn => false,
13161                                           prepareRuleDescsIn => false,
13162                                           transactionIdIn => transactionIdIn,
13163                                           ameApplicationIdIn => null,
13164                                           fndApplicationIdIn => applicationIdIn,
13165                                           transactionTypeIdIn => transactionTypeIn);
13166       end if;
13167       ame_engine.unlockTransaction(fndApplicationIdIn => applicationIdIn,
13168                                    transactionIdIn => transactionIdIn,
13169                                    transactionTypeIdIn => transactionTypeIn);
13170       exception
13171         when badForwardeeException then
13172           ame_engine.unlockTransaction(fndApplicationIdIn => applicationIdIn,
13173                                        transactionIdIn => transactionIdIn,
13174                                        transactionTypeIdIn => transactionTypeIn);
13175           errorCode := -20001;
13176           if transactionTypeIn is not null then
13177             errorMessage := ame_util.getMessage(applicationShortNameIn => 'PER',
13178                                                 messageNameIn => 'AME_400298_API_FOR_NOT_VALID',
13179                                                 tokenNameOneIn => 'TRANSACTION_ID',
13180                                                 tokenValueOneIn => transactionIdIn,
13181                                                 tokenNameTwoIn => 'TRANSACTION_TYPE',
13182                                                 tokenValueTwoIn => transactionTypeIn);
13183           else
13184             errorMessage := ame_util.getMessage(applicationShortNameIn => 'PER',
13185                                                 messageNameIn => 'AME_400066_API_FOR_NOT_VALID2',
13186                                                 tokenNameOneIn => 'TRANSACTION_ID',
13187                                                 tokenValueOneIn => transactionIdIn);
13188           end if;
13189           ame_util.runtimeException(packageNameIn => 'ame_engine',
13190                                     routineNameIn => 'updateApprovalStatus',
13191                                     exceptionNumberIn => errorCode,
13192                                     exceptionStringIn => errorMessage);
13193           raise_application_error(errorCode,
13194                                   errorMessage);
13195         when apiInsertionException then
13196           ame_engine.unlockTransaction(fndApplicationIdIn => applicationIdIn,
13197                                        transactionIdIn => transactionIdIn,
13198                                        transactionTypeIdIn => transactionTypeIn);
13199           errorCode := -20001;
13200           errorMessage :=
13201           ame_util.getMessage(applicationShortNameIn => 'PER',
13202                               messageNameIn => 'AME_400246_API_FWD_SAME_VALUE');
13203           ame_util.runtimeException(packageNameIn => 'ame_engine',
13204                                     routineNameIn => 'updateApprovalStatus',
13205                                     exceptionNumberIn => errorCode,
13206                                     exceptionStringIn => errorMessage);
13207           raise_application_error(errorCode,
13208                                   errorMessage);
13209         when badStatusException then
13210           ame_engine.unlockTransaction(fndApplicationIdIn => applicationIdIn,
13211                                        transactionIdIn => transactionIdIn,
13212                                        transactionTypeIdIn => transactionTypeIn);
13213           errorCode := -20001;
13214           if transactionTypeIn is not null then
13215             errorMessage := ame_util.getMessage(applicationShortNameIn => 'PER',
13216                                                 messageNameIn => 'AME_400247_API_APPR_STAT_VALUE',
13217                                                 tokenNameOneIn => 'TRANSACTION_ID',
13218                                                 tokenValueOneIn => transactionIdIn,
13219                                                 tokenNameTwoIn => 'TRANSACTION_TYPE',
13220                                                 tokenValueTwoIn => transactionTypeIn,
13221                                                 tokenNameThreeIn => 'APPROVED_STATUS',
13222                                                 tokenValueThreeIn => ame_util.approvedStatus,
13223                                                 tokenNameFourIn => 'APPROVED_FORWARD_STATUS',
13224                                                 tokenValueFourIn => ame_util.approveAndForwardStatus,
13225                                                 tokenNameFiveIn => 'EXCEPTION_STATUS',
13226                                                 tokenValueFiveIn => ame_util.exceptionStatus ,
13227                                                 tokenNameSixIn => 'FORWARD_STATUS',
13228                                                 tokenValueSixIn => ame_util.forwardStatus,
13229                                                 tokenNameSevenIn => 'REJECT_STATUS',
13230                                                 tokenValueSevenIn => ame_util.rejectStatus);
13231           else
13232             errorMessage := ame_util.getMessage(applicationShortNameIn => 'PER',
13233                                                 messageNameIn => 'AME_400064_API_APPR_STAT_VAL2',
13234                                                 tokenNameOneIn => 'TRANSACTION_ID',
13235                                                 tokenValueOneIn => transactionIdIn,
13236                                                 tokenNameTwoIn => 'APPROVED_STATUS',
13237                                                 tokenValueTwoIn => ame_util.approvedStatus,
13238                                                 tokenNameThreeIn => 'APPROVED_FORWARD_STATUS',
13239                                                 tokenValueThreeIn => ame_util.approveAndForwardStatus,
13240                                                 tokenNameFourIn => 'EXCEPTION_STATUS',
13241                                                 tokenValueFourIn => ame_util.exceptionStatus ,
13242                                                 tokenNameFiveIn => 'FORWARD_STATUS',
13243                                                 tokenValueFiveIn => ame_util.forwardStatus,
13244                                                 tokenNameSixIn => 'REJECT_STATUS',
13245                                                 tokenValueSixIn => ame_util.rejectStatus);
13246           end if;
13247           ame_util.runtimeException(packageNameIn => 'ame_engine',
13248                                     routineNameIn => 'updateApprovalStatus',
13249                                     exceptionNumberIn => errorCode,
13250                                     exceptionStringIn => errorMessage);
13251           raise_application_error(errorCode,
13252                                   errorMessage);
13253         when others then
13254           ame_engine.unlockTransaction(fndApplicationIdIn => applicationIdIn,
13255                                        transactionIdIn => transactionIdIn,
13256                                        transactionTypeIdIn => transactionTypeIn);
13257           ame_util.runtimeException(packageNameIn => 'ame_engine',
13258                                     routineNameIn => 'updateApprovalStatus',
13259                                     exceptionNumberIn => sqlcode,
13260                                     exceptionStringIn => sqlerrm);
13261           raise;
13262     end updateApprovalStatus;
13263   procedure updateInsertions(indexIn in integer) as
13264     tempIndex integer;
13265     approverInsertionOrder integer;
13266     deletionInsertionOrder integer;
13267     begin
13268       if engStInsertionIndexes.exists(indexIn) then
13269         deletionInsertionOrder := engStInsertionIndexes(indexIn);
13270         tempIndex := engStInsertionIndexes.next(indexIn);
13271         while engStInsertionIndexes.exists(tempIndex) loop
13272           approverInsertionOrder := engStInsertionIndexes(tempIndex);
13273           if approverInsertionOrder > deletionInsertionOrder then
13274             update ame_temp_insertions
13275                set parameter = parameter - 1
13276              where insertion_order = approverInsertionOrder
13277                and application_id = engAmeApplicationId
13278                and transaction_id = engTransactionId
13279                and order_type = ame_util.absoluteOrder;
13280           end if;
13281           tempIndex := engStInsertionIndexes.next(tempIndex);
13282         end loop;
13283       end if;
13284     end updateInsertions;
13285   procedure setDeviationReasonDate(reasonIn in varchar2,dateIn in date) as
13286   begin
13287     engTempReason := reasonIn;
13288     engTempDate := dateIn;
13289   end setDeviationReasonDate;
13290 end ame_engine;