[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;