[Home] [Help]
PACKAGE BODY: APPS.AME_ENGINE
Source
1 PACKAGE BODY AME_ENGINE as
2 /* $Header: ameeengi.pkb 120.60.12020000.3 2013/02/14 10:49:49 nivsubra ship $ */
3 /*************************************************************************************
4 package variables
5 All engine package variables' names begin with the prefix 'eng'. All engine package
6 variables are private.
7 *************************************************************************************/
8 /* transaction identifiers */
9 engAmeApplicationId integer;
10 engFndApplicationId integer;
11 engTransactionId ame_temp_old_approver_lists.transaction_id%type;
12 engTransactionTypeId ame_calling_apps.transaction_type_id%type;
13 /* engTransactionIsLocked is for the transaction-locking utilities used by the APIs. */
14 engTransactionIsLocked boolean := false;
15 /*
16 engIsLocalTransaction indicates whether the current engine cycle originates in an API
17 call or a test-tab routine. If the test tab is testing a real transaction ID, it should
18 set engIsTestTransaction to false (via a call to updateTransactionState), and it should
19 set engIsLocalTransaction to true. The API should set both engIsTestTransaction and
20 engIsLocalTransaction to false. The ame_util.runtimeException checks engIsLocalTransaction
21 to determine whether to log an exception to the Workflow context stack.
22 */
23 engIsLocalTransaction boolean := true;
24 /*
25 engIsTestTransaction indicates whether the current transaction is a test transaction.
26 If so, the engine fetches the transaction's attribute values from ame_test_trans_att_values.
27 engIsTestTransaction is initialized to true so ame_util.runtimeException will see
28 a value of true in the absence of a call to updateTransactionState, before the
29 call to ame_util.runtimeException. That is, unless a call to updateTransactionState
30 sets this variable's value, we assume the transaction is a test transaction, to
31 avoid writing spurious exceptions to the Workflow context stack.
32 */
33 engIsTestTransaction boolean := true;
34 /*
35 updateTransactionState sets the following variables. They indicate which parts of its
36 cycle the engine should or should not execute.
37 */
38 engPrepareItemData boolean;
39 engPrepareRuleDescs boolean;
40 engPrepareApproverTree boolean;
41 engItemDataPrepared boolean;
42 engPrepareRuleIds boolean;
43 engProcessPriorities boolean;
44 engProcessProductionActions boolean;
45 engProcessProductionRules boolean;
46 engUpdateCurrentApproverList boolean;
47 engUpdateOldApproverList boolean;
48 /* configuration-variable caches */
49 engConfigVarNames ame_util.longStringList; /* kept compact */
50 engConfigVarValues ame_util.longStringList; /* kept compact */
51 /*
52 Generally, all runtime queries should use engEffectiveRuleDate in their date logic, to make sure
53 they all rely on the same snapshot of AME data. (Failure to do this can lead to inconsistent data
54 in different parts of the engine cycle, which could make the engine crash.)
55 */
56 engEffectiveRuleDate date;
57 engEvalPrioritiesPerItem boolean;
58 engForwardingBehaviors ame_util.stringList; /* kept compact */
59 /*
60 engPriorityModes and engPriorityThresholds are indexed by rule-type constant, so their
61 indexes run from zero to seven.
62 */
63 engPriorityModes ame_util.stringList;
64 engPriorityThresholds ame_util.idList;
65 /*
66 Approval-group members are cached (once fetched as required) in the engGroup variables. These
67 lists are compact. All of a group's members are in a consecutive order consistent with the
68 group members' order numbers (whether static or dynamic in the group definition).
69 */
70 engGroupMemberGroupIds ame_util.idList;
71 engGroupMemberNames ame_util.longStringList;
72 engGroupMemberOrderNumbers ame_util.idList;
73 engGroupMemberDisplayNames ame_util.longStringList;
74 engGroupMemberOrigSystems ame_util.stringList;
75 engGroupMemberOrigSystemIds ame_util.idList;
76 -- Array to keep track if approval group needs to be rerun for each item class, item ID
77 engGroupUseItemBind ame_util.charList;
78 /* approver lists */
79 engDeletedApproverList ame_util.approversTable2; /* kept compact */
80 engInsertedApproverList ame_util.approversTable2; /* kept compact */
81 engOldApproverList ame_util.approversTable2; /* kept compact, read only */
82 /* lists related to approver insertion and deletion */
83 engInsertionOrderTypeList ame_util.stringList; /* corresponds in order to engInsertedApproverList */
84 engInsertionParameterList ame_util.longestStringList; /* corresponds in order to engInsertedApproverList */
85 engInsertionIsSpecialForwardee ame_util.charList; /* ame_util.booleanTrue if insertee is a special forwardee */
86 engInsApproverIndex ame_util.idList; /*maintain the approver index for the insertion*/
87 /* action-type configuration data, all sparse, indexed by action-type ID */
88 engActionTypeChainOrderModes ame_util.charList;
89 engActionTypeOrderNumbers ame_util.idList;
90 engActionTypeVotingRegimes ame_util.charList;
91 engActionTypeNames ame_util.stringList;
92 engActionTypeUsages ame_util.idList;
93 engActionTypePackageNames ame_util.stringList;
94 /*
95 list-modification condition caches, all sparse, indexed by the ID of the rule using the LM condition,
96 not by the condition ID (It's more efficient to index by rule ID.)
97 */
98 engLMParameterOnes ame_util.stringList;
99 engLMParameterTwos ame_util.longStringList;
100 /*
101 The item-class usages are stored in engItemClassIds, engItemClassNames, engItemClassOrderNumbers,
102 engItemClassParModes, and engItemClassSublistModes. All of these are compact, and ordered by
103 item_class_order_number order. If engItemClassIds(i) is a given item class' item-class ID, then
104 engItemClassIndexes(engItemClassIds(i)) = i. So the index of the row in the item-class-usage
105 data structures for an item class with the item-class ID item_class_id is
106 engItemClassIndexes(item_class_id). engItemClassItemIdIndexes(i) is the index of the first item
107 ID in itemIds of the item class with ID engItemClassIds(i).
108 */
109 engItemClassIds ame_util.idList;
110 engItemClassIndexes ame_util.idList;
111 engItemClassItemIdIndexes ame_util.idList;
112 engItemClassNames ame_util.stringList;
113 engItemClassOrderNumbers ame_util.idList;
114 engItemClassParModes ame_util.charList;
115 engItemClassSublistModes ame_util.charList;
116 /*
117 engItemCounts(i) is the number of items of the item class with item-class ID
118 engItemClassIds(i). engItemIds contains the item-ID lists returned by all
119 of the item classes' item-ID queries, in item_class_order_number order.
120 */
121 engItemCounts ame_util.idList; /* compact */
122 engItemIds ame_util.stringList; /* compact */
123 /* attributes */
124 engAttributeIsStatics ame_util.charList; /* indexed by attribute id */
125 engAttributeItemClassIds ame_util.idList; /* indexed by attribute id */
126 engAttributeNames ame_util.stringList; /* indexed by attribute id */
127 engAttributeTypes ame_util.stringList; /* indexed by attribute id */
128 /* New arrays to store the query details and whether they need to be evaluated
129 for each itemClass and itemID */
130 engAttributeQueries ame_util.longestStringList;
131 engAttributeVariant ame_util.stringList;
132 /*
133 The attribute values are kept compact. The values of the attribute with ID i
134 are stored starting at the index engAttributeValueIndexes(i), in the order
135 that their item IDs occur in engItemIds.
136 */
137 engAttributeValueIndexes ame_util.idList; /* indexed by attribute id */
138 engAttributeValues1 ame_util.attributeValueList; /* compact */
139 engAttributeValues2 ame_util.attributeValueList; /* compact */
140 engAttributeValues3 ame_util.attributeValueList; /* compact */
141 /*
142 engHeaderConditionValues caches the truth values of conditions on
143 attributes in the header item class. It is indexed by condition ID.
144 */
145 engHeaderConditionValues ame_util.charList;
146 /*
147 The engACUsage variables store active condition usages and related data.
148 engACUsageRulePriorities, engACUsageRuleTypes, and engACUsageRuleApprCategories
149 are indexed by rule ID; the other variables are indexed consecutively, and are
150 ordered first by item-class ID (with null item-class IDs last), then by rule ID.
151 The first order-by is so the engine can efficiently access the related engAC and
152 engACU data structures by item-class ID. (List-modification rules have null
153 item-class IDs, so they'll get processed last.) The second order-by is so the
154 engine can efficiently do weak per-item evaluation for rules in the header item
155 class, when that is required. engACUsageFirstIndexes(item_class_id) is the index
156 of the first row in the engACUsage variables for the item class with ID
157 item_class_id. That is, engACUsageFirstIndexes is indexed by item-class
158 ID. An item class may have no active condition usages. In this case,
159 engACUsageFirstIndexes.exists(item_class_id) returns false.
160 engACUsageItemClassCounts(item_class_id) is the number of rows in the
161 engACUsage variables for the item class with ID item_class_id, starting at
162 the index engACUsageFirstIndexes(item_class_id).
163 */
164 engACUsageConditionIds ame_util.idList;
165 engACUsageFirstIndexes ame_util.idList;
166 engACUsageItemClassCounts ame_util.idList;
167 engACUsageRuleIds ame_util.idList;
168 engACUsageRulePriorities ame_util.idList; /* indexed by rule ID */
169 engACUsageRuleTypes ame_util.idList; /* indexed by rule ID */
170 engACUsageRuleApprCategories ame_util.charList; /* indexed by rule ID */
171 /*
172 The engAC variables store properties of conditions in the active condition usages.
173 They are indexed by condition ID.
174 */
175 engACAttributeIds ame_util.idList;
176 engACConditionTypes ame_util.stringList;
177 engACIncludeLowerLimits ame_util.charList;
178 engACIncludeUpperLimits ame_util.charList;
179 engACParameterOnes ame_util.stringList;
180 engACParameterThrees ame_util.stringList;
181 engACParameterTwos ame_util.longStringList;
182 /*
183 engACStringValues stores string values for active conditions on string attributes.
184 It is ordered by condition ID. engACStringValueFirstIndexes(condition_id) is the
185 index of the first row in engACStringValues for the condition with ID condition_id.
186 That is, engACStringValueFirstIndexes is indexed by condition ID.
187 engACStringValueCounts(condition_id) is the number of rows in
188 engACStringValues for the condition with ID condition_id, starting at
189 the index engACStringValueFirstIndexes(condition_id).
190 */
191 engACStringValueCounts ame_util.idList;
192 engACStringValueFirstIndexes ame_util.idList;
193 engACStringValues ame_util.attributeValueList;
194 /*
195 >> engApp indexing
196 The variables
197 engAppHandlerFirstIndex
198 engAppHandlerLastIndex
199 are single-valued. The variables
200 engAppLMSubItemClassIds
201 engAppLMSubItemIds
202 are indexed by rule ID. All other engApp variables are stored in a common, dense
203 order, with each row representing the application of a single rule to a single
204 item. (Thus the same rule ID can appear several times in engAppRuleIds, as long
205 as when i <> j, if engAppRuleIds(i) = engAppRuleIds(j) then engAppAppItemIds(i)
206 <> engAppItemIds(j) and of course engAppRuleItemClassIds(i) does not identify the
207 header item class.) The rules determining the ordering of the dense engApp
208 variables change somewhat at different engine-processing stages; see below.
209 >> engApp semantics
210 Most of the engApp variables store the list of applicable rules. The following
211 variables store actual rule and rule-usage properties:
212 engAppActionTypeIds
213 engAppApproverCategories
214 engAppPriorities
215 engAppRuleIds
216 engAppRuleItemClassIds
217 engAppRuleTypes.
218 The variables
219 engAppParameters
220 engAppParameterTwos
221 store the parameters of the rules' actions. The variables
222 engAppItemClassIds
223 engAppItemIds
224 store the item-class IDs and item IDs of the item that satisfies a rule. The
225 variable
226 engAppAppItemIds
227 contains the IDs of the items to which the rules apply (and these items always
228 belong to the item classes identified by engAppRuleItemClassIds). Usually the item
229 that satisfies a rule is the same as the item to which the rule applies. That is,
230 usually
231 engAppRuleItemClassIds(i) = engAppItemClassIds(i)
232 engAppAppItemIds(i) = engAppItemIds(i).
233 However, if per-item evaluation is enabled, these equalities fail for a rule
234 that contains a subordinate-item-class level condition. In this case,
235 engAppRuleItemClassIds(i) identifies the header item class, and
236 engAppAppItemIds(i) is the transaction ID; but engAppItemClassIds(i) and
237 engAppItemIds(i) identify a subordinate item-class item satisfying the
238 subordinate-item-class level conditions. Note that the engine treats list-
239 modification and substitution rules as applying to all item classes and items, so
240 engAppItemClassIds
241 engAppItemIds
242 are null for rules of these types. These rules' satisfying item classes and items
243 are stored instead in
244 engAppLMSubItemClassIds
245 engAppLMSubItemIds.
246 Finally, the variables
247 engAppHandlerFirstIndex
248 engAppHandlerLastIndex
249 mark the first and last rows in the other engApp variables that the procedure
250 processActionType is currently processing. They have no meaning outside this context.
251 >> engApp processing
252 The procedure evaluateRules populates
253 engAppRuleIds
254 engAppRuleTypes
255 engAppRuleItemClassIds
256 engAppPriorities
257 engAppApproverCategories
258 engAppItemClassIds
259 engAppItemIds
260 engAppAppItemIds
261 leaving them compact and sorted lexicographically by these values:
262 the item-class order numbers of the engAppRuleItemClassIds values
263 the engAppRuleItemClassIds values themselves
264 the engAppItemClassIds values
265 the engAppRuleTypes values.
266 The processRelativePriorities procedure (called by evaluateRules)
267 1. deletes a row in the compact engApp lists if the rule represented by the row
268 is of insufficient relative priority.
269 2. re-compacts the same lists (preserving the above lexicographic ordering).
270 At this point, a rule with several actions still appears just once in the engApp
271 lists. The procedure fetchApplicableActions
272 1. populates engAppActionTypeIds, engAppParameters, and engAppParameterTwos.
273 2. splits out the actions in a rule so that the rule has one row in the engApp
274 lists for each of the rule's actions.
275 3. converts each combination rule's rule type to the rule type that corresponds
276 with the rule's action type.
277 4. re-sorts the lists lexicographically by these values:
278 rule's item-class order number
279 rule's item-class ID
280 item ID of the item to which the rule applies
281 rule type
282 action-type order number
283 action-type ID.
284 fetchApplicableActions deletes engAppPriorities because priorities have already been
285 processed; so engAppPriorities should not be referenced after fetchApplicableActions
286 is called. Next, processExceptions
287 1. deletes from the engApp variables any list-creation (authority) rules
288 suppressed by the exception rules.
289 2. re-compacts the lists (preserving the above lexicographic ordering).
290 3. converts the exception rules to list-creation rules.
291 processExceptions occurs in the engine algorithm after applicable actions have been
292 fetched, so that the actions of any list-creation rules suppressed by exception
293 rules will have been fetched unnecessarily. The assumption here is that exception
294 rules are deprecated, so if performance becomes an issue, exception rules should be
295 converted to list-creation rules with appropriate priorities.
296 */
297 engAppActionTypeIds ame_util.idList;
298 engAppAppItemIds ame_util.stringList;
299 engAppApproverCategories ame_util.charList;
300 engAppHandlerFirstIndex integer;
301 engAppHandlerLastIndex integer;
302 engAppItemClassIds ame_util.idList;
303 engAppItemIds ame_util.stringList;
304 engAppLMSubItemClassIds ame_util.idList;
305 engAppLMSubItemIds ame_util.stringList;
306 engAppParameters ame_util.stringList;
307 engAppParameterTwos ame_util.stringList;
308 engAppPriorities ame_util.idList;
309 engAppRuleIds ame_util.idList;
310 engRuleAppliedYN ame_util.charList;
311 engAppRuleItemClassIds ame_util.idList;
312 engAppRuleTypes ame_util.idList;
313 /*
314 The engAppPerAppProd variables contain per-approver productions sorted by rule ID.
315 fetchApplicableActions populates these variables. Then populateEngStVariables transfers
316 the values into engStProductionIndexes, engStVariableNames, and engStVariableValues,
317 after the approver list has been built. Finally processRepeatedApprovers modifies the
318 values as it suppresses repeated approvers. All of the per-approver productions generated
319 by a rule appear in consecutive order in the engAppPerAppProd variables.
320 engAppPerAppProdFirstIndexes(i) is the index of the first row in the other
321 engAppPerAppProd variables that contains a production generated by the rule with ID i.
322 */
323 engAppPerAppProdFirstIndexes ame_util.idList;
324 engAppPerAppProdRuleIds ame_util.idList;
325 engAppPerAppProdVariableNames ame_util.stringList;
326 engAppPerAppProdVariableValues ame_util.stringList;
327 /* engRepeatSubstitutions is a new private engine flag indicating whether the substitution handler
328 needs to be called a second time after adhoc insertions and surrogate processing */
329 engRepeatSubstitutions boolean;
330 /* engAppSub variables store relevant data needed to call the substitution handler a second time. */
331 engAppSubHandlerFirstIndex integer;
332 engAppSubHandlerLastIndex integer;
333 /*
334 The engSt variables contain approval-process state data for AME API code to output.
335 Here are descriptions of each engSt variable.
336 - engStApprovalProcessCompleteYN is a pseudoboolean indicating whether the entire
337 transaction's approval process is complete.
338 - engStApprovers is the current approver list. It is compact.
339 - engStItemIds, engStItemClasses, engStItemIndexes, and engStItemSources relate approvers in
340 engStApprovers to the items requiring them. If the item_id and item_class fields of an
341 approverRecord2 in engStApprovers are null, several items require the approver. (The
342 converse is not true. The item_id and item_class fields of an approver with the status
343 ame_util.repeatedStatus are not nulled, even though the approver occurs several times.
344 Only the first occurrence of an approver within the applicable repeated-approvers grouping
345 will have null item_id and item_class values, when several items require the approver.)
346 If such an approver is at index i in engStApprovers, and engStItemIndexes(j) = i, then
347 engStItemIds(j) is the ID of an item requiring the approver, engStItemClasses(j) is the
348 corresponding item class, and engStItemSources(j) is the source field indicating which
349 rules require the approver for that item. (There will be at least two such "rows" in
350 these lists, for an approver in engStApprovers required by multiple items.)
351 - engStProductionIndexes, engStVariableNames, and engStVariableValues store per-approver
352 productions. A variable-name/value pair is stored at the same index in
353 engStVariableNames and engStVariableValues. Several productions can be assigned to a
354 single approver, so engStProductionIndexes contains for each production the index of the
355 approverRecord2 in engStApprovers to which the production is assigned. That is, if
356 engStProductionIndexes(i) = j, then the production in engStVariableNames(i) and
357 engStVariableValues(i) is assigned to engStApprovers(j).
358 - engStTransVariableNames and engStTransVariableValues store per-transaction productions
359 in compact lists.
360 - engStRuleIds, engStRuleDescriptions, engStRuleIndexes, and engStSourceTypes classify
361 approvers in engStApprovers according to their sources (the reasons for their occurrence
362 in the approver list). When an approver is required by one or more rules, the rules are
363 identified in engStRuleIds. More particularly: every approverRecord2 in engStApprovers
364 has at least one row in engStRuleIndexes, engStSourceTypes and engStRuleIds. If
365 engStRuleIndexes(i) = j, then the values in engStSourceTypes(i) and engStRuleIds(i)
366 pertain to the approver in engStApprovers(j). Every approver in engStApprovers has only
367 one source value, no matter how many rules required the approver. That is, if
368 engStRuleIndexes(i1) = j and engStRuleIndexes(i2) = j for i1 <> i2, then
369 engStSourceTypes(i1) = engStSourceTypes(i2). Some source values indicate that an
370 approver is not required by any rules, but is present for other reasons. In such cases,
371 if the approver is at index i and engStSourceTypes(j) = i, then engStRuleIds(j) is null.
372 - engStItemAppProcesscompleteYN is compact. It stores the approval-process status per item.
373 It is ordered so that the approval-process status of engItemIds(i) is
374 engStItemAppProcessCompleteYN(i).
375 */
376 engStApprovalProcessCompleteYN ame_util.charType;
377 engStApprovers ame_util.approversTable2;
378 /* This global variable stores the approver tree */
379 engStApproversTree ame_util.approversTreeTable;
380 engStItemClasses ame_util.stringList;
381 engStItemIds ame_util.stringList;
382 engStItemIndexes ame_util.idList;
383 engStItemSources ame_util.longStringList;
384 engStProductionIndexes ame_util.idList;
385 /* Following two global variables to store repeated indexes */
386 engStRepeatedIndexes ame_util.idList;
387 engStRepeatedAppIndexes ame_util.idList;
388 engStRuleDescriptions ame_util.stringList;
389 engStRuleIds ame_util.idList;
390 engStRuleIndexes ame_util.idList;
391 engStSourceTypes ame_util.stringList;
392 /* Following two global variables store the list of suspended items */
393 engStSuspendedItems ame_util.stringList;
394 engStSuspendedItemClasses ame_util.stringList;
395 engStVariableNames ame_util.stringList;
396 engStVariableValues ame_util.stringList;
397 engStProductionsTable ame_util2.productionsTable;
398 engStItemAppProcessCompleteYN ame_util.charList;
399 engStInsertionIndexes ame_util.idList;
400 engInsertionOrderList ame_util.idList;
401 /*eng deviation list*/
402 engDeviationResultList ame_approver_deviation_pkg.deviationReasonList;
403 engInsertionReasonList ame_util.stringList;
404 engInsertionDateList ame_util.dateList;
405 engSuppressionDateList ame_util.dateList;
406 engSupperssionReasonList ame_util.stringList;
407 engTempReason varchar2(50);
408 engTempDate date;
409 engRepSubFlag ame_util.charType;
410 engSATOFlag ame_util.charType;
411 /*************************************************************************************
412 forward declarations of private functions
413 *************************************************************************************/
414 /******************************** boolean functions *********************************/
415 /*
416 conditionIsSatisfied assumes that itemIndexIn indexes an item ID in engItemIds, and
417 that this item is of the same item class as that of the attribute used by the
418 condition with ID conditionIdIn.
419 */
420 function conditionIsSatisfied(conditionIdIn in integer,
421 itemClassIdIn in integer,
422 itemIndexIn in integer) return boolean;
423 /********************************* fetch functions **********************************/
424 function fetchAmeApplicationId(fndApplicationIdIn in integer,
425 transactionTypeIdIn in varchar2 default null) return integer;
426 /********************************** get functions ***********************************/
427 function getItemIndex(itemClassIdIn in integer,
428 itemIdIn in varchar2) return integer;
429 function getItemOffset(itemClassIdIn in integer,
430 itemIdIn in varchar2) return integer;
431 /********************************** sort functions **********************************/
432 /* compareApplicableRules is a subroutine of the sortApplicableRules procedure. */
433 function compareApplicableRules(index1In in integer,
434 index2In in integer,
435 compareActionTypesIn in boolean) return boolean;
436 function getTestVariantAttValue(attributeIdIn in integer,
437 itemClassIdIn in integer,
438 itemIdIn in varchar2) return number;
439 function isVariant(attributeIdIn in integer) return boolean;
440 /*************************************************************************************
441 forward declarations of private procedures
442 *************************************************************************************/
443 procedure addApproverToTree
444 (approverRecordIn in ame_util.approverRecord2
445 ,approverIndexIn in integer
446 ,approverLocationIn in boolean default ame_util.lastAmongEquals);
447 procedure calculateApproverOrderNumbers;
448 procedure compactEngAppLists(compactPrioritiesIn in boolean,
449 compactActionTypeIdsIn in boolean,
450 compactParametersIn in boolean);
451 procedure doPerItemRuleEvaluation(itemClassIdIn in integer,
452 itemIndexIn in varchar2);
453 procedure doStrictHeaderRuleEvaluation(itemClassIndexIn in integer,
454 itemClassIdIn in integer);
455 procedure doWeakHeaderRuleEvaluation(itemClassIndexIn in integer,
456 itemClassIdIn in integer);
457 procedure evaluateRules;
458 procedure fetchActiveConditionUsages;
459 procedure fetchApplicableActions;
460 procedure fetchAttributeValues(fetchInactivesIn in boolean);
461 procedure fetchConfigVars;
462 procedure fetchDeletedApprovers;
463 procedure fetchFndApplicationId(applicationIdIn in integer,
464 fndApplicationIdOut out nocopy integer,
465 transactionTypeIdOut out nocopy varchar2);
466 procedure fetchInsertedApprovers;
467 procedure fetchItemClassData;
468 procedure fetchOldApprovers;
469 procedure fetchRuntimeGroup(groupIdIn in integer);
470 procedure finalizeTree(parentIndexIn in integer default 1
471 ,maximumOrderOut out nocopy integer
472 ,approvalStatusOut out nocopy integer
473 ,rejectedItemsExistOut out nocopy boolean);
474 procedure getLMCondition(ruleIdIn in integer,
475 parameterOneOut out nocopy varchar2,
476 parameterTwoOut out nocopy varchar2);
477 procedure insertIntoTransApprovalHistory
478 (transactionIdIn ame_trans_approval_history.transaction_id%type
479 ,applicationIdIn ame_trans_approval_history.application_id%type
480 ,orderNumberIn ame_trans_approval_history.order_number%type
481 ,nameIn ame_trans_approval_history.name%type
482 ,appCategoryIn ame_trans_approval_history.approver_category%type
483 ,itemClassIn ame_trans_approval_history.item_class%type
484 ,itemIdIn ame_trans_approval_history.item_id%type
485 ,actionTypeIdIn ame_trans_approval_history.action_type_id%type
486 ,authorityIn ame_trans_approval_history.authority%type
487 ,statusIn ame_trans_approval_history.status%type
488 ,grpOrChainIdIn ame_trans_approval_history.group_or_chain_id%type
489 ,occurrenceIn ame_trans_approval_history.occurrence%type
490 ,apiInsertionIn ame_trans_approval_history.api_insertion%type
491 ,memberOrderNumberIn ame_trans_approval_history.member_order_number%type
492 ,notificationIdIn ame_trans_approval_history.notification_id%type
493 ,userCommentsIn ame_trans_approval_history.user_comments%type
494 ,dateClearedIn ame_trans_approval_history.date_cleared%type
495 ,historyTypeIn varchar2);
496 procedure parseForwardingBehaviors(forwardingBehaviorsIn in varchar2);
497 procedure parsePriorityModes(priorityModesIn in varchar2);
498 procedure populateEngStVariables;
499 procedure prepareItemData(approverIndexesIn in ame_util.idList default ame_util.emptyIdList
500 ,itemIndexesOut out nocopy ame_util.idList
501 ,itemItemClassesOut out nocopy ame_util.stringList
502 ,itemIdsOut out nocopy ame_util.stringList
503 ,itemSourcesOut out nocopy ame_util.longStringList);
504 procedure preparePerApproverProductions
505 (approverIndexesIn in ame_util.idList default ame_util.emptyIdList
506 ,itemIndexesIn in ame_util.idList default ame_util.emptyIdList
507 ,itemSourcesIn in ame_util.longStringList default ame_util.emptyLongStringList
508 ,prodIndexesOut out nocopy ame_util.idList
509 ,productionNamesOut out nocopy ame_util.stringList
510 ,productionValuesOut out nocopy ame_util.stringList);
511 procedure prepareRuleData;
512 procedure processActionType;
513 procedure processAdHocInsertions;
514 procedure processSuppressions;
515 procedure processRelativePriorities;
516 procedure processRepeatedApprovers;
517 procedure processRules(processOnlyProductionsIn in boolean default false);
518 procedure processUnresponsiveApprovers;
519 procedure populateInsertionIndexes(indexIn in integer
520 ,insertionOrderIn in integer);
521 procedure repeatSubstitutions;
522 procedure setContext(isTestTransactionIn in boolean,
523 isLocalTransactionIn in boolean,
524 fetchConfigVarsIn in boolean,
525 fetchOldApproversIn in boolean,
526 fetchInsertionsIn in boolean,
527 fetchDeletionsIn in boolean,
528 fetchAttributeValuesIn in boolean,
529 fetchInactiveAttValuesIn in boolean,
530 processProductionActionsIn in boolean,
531 processProductionRulesIn in boolean,
532 updateCurrentApproverListIn in boolean,
533 updateOldApproverListIn in boolean,
534 processPrioritiesIn in boolean,
535 prepareItemDataIn in boolean,
536 prepareRuleIdsIn in boolean,
537 prepareRuleDescsIn in boolean,
538 prepareApproverTreeIn in boolean default false,
539 transactionIdIn in varchar2,
540 ameApplicationIdIn in integer default null,
541 fndApplicationIdIn in integer default null,
542 transactionTypeIdIn in varchar2 default null);
543 procedure setInsertedApprovalStatus(currentApproverIndexIn in integer
544 ,approvalStatusIn in varchar2);
545
546 procedure sortApplicableRules(sortByActionTypeIn in boolean);
547 procedure updateOldApproverList;
548 /*************************************************************************************
549 functions
550 *************************************************************************************/
551 /******************************** boolean functions *********************************/
552 function approversMatch(approverRecord1In in ame_util.approverRecord2,
553 approverRecord2In in ame_util.approverRecord2) return boolean as
554 begin
555 /* The following if statement's conditions are in decreasing order of specificity for efficiency. */
556 if(approverRecord1In.name = approverRecord2In.name and
557 approverRecord1In.occurrence = approverRecord2In.occurrence and
558 approverRecord1In.group_or_chain_id = approverRecord2In.group_or_chain_id and
559 approverRecord1In.action_type_id = approverRecord2In.action_type_id and
560 approverRecord1In.item_id = approverRecord2In.item_id and
561 approverRecord1In.item_class = approverRecord2In.item_class) then
562 return(true);
563 end if;
564 return(false);
565 exception
566 when others then
567 ame_util.runtimeException(packageNameIn => 'ame_engine',
568 routineNameIn => 'approversMatch',
569 exceptionNumberIn => sqlcode,
570 exceptionStringIn => sqlerrm);
571 raise;
572 return(false);
573 end approversMatch;
574 function checkAttributeVariant(attributeIdIn in integer) return varchar2 as
575 begin
576 if (engAttributeNames(attributeIdIn) = ame_util.jobLevelStartingPointAttribute or
577 engAttributeNames(attributeIdIn) = ame_util.nonDefStartingPointPosAttr or
578 engAttributeNames(attributeIdIn) = ame_util.nonDefPosStructureAttr or
579 engAttributeNames(attributeIdIn) = ame_util.supStartingPointAttribute or
580 engAttributeNames(attributeIdIn) = ame_util.firstStartingPointAttribute or
581 engAttributeNames(attributeIdIn) = ame_util.secondStartingPointAttribute ) then
582 return(ame_util.booleanTrue);
583 else
584 return(ame_util.booleanFalse);
585 end if;
586 end;
587 function getVariantAttributeValue(attributeIdIn in integer,
588 itemClassIn in varchar2,
589 itemIdIn in varchar2) return number as
590 dynamicCursor integer;
591 dynamicQuery ame_util.longestStringType;
592 rowsFound integer;
593 tempAttributeValues1 dbms_sql.varchar2_table;
594 begin
595 if engIsTestTransaction then
596 if checkAttributeVariant(attributeIdIn) = ame_util.booleanTrue then
597 return (getTestVariantAttValue(attributeIdIn => attributeIdIn
598 ,itemClassIdIn => getItemClassId(itemClassNameIn => itemClassIn)
599 ,itemIdIn => itemIdIn));
600 else
601 return(engAttributeValues1(engAttributeValueIndexes(attributeIdIn)));
602 end if;
603 end if;
604 /* fetch the value for real transactions using the dynamic query */
605 if(engAttributeVariant.exists(attributeIdIn))then
606 dynamicQuery := ame_util.removeReturns(stringIn => engAttributeQueries(attributeIdIn),
607 replaceWithSpaces => true);
608 dynamicCursor := dbms_sql.open_cursor;
609 dbms_sql.parse(dynamicCursor,
610 dynamicQuery,
611 dbms_sql.native);
612 if(instrb(dynamicQuery, ame_util.transactionIdPlaceholder) > 0) then
613 dbms_sql.bind_variable(dynamicCursor,
614 ame_util.transactionIdPlaceholder,
615 engTransactionId,
616 50); /* ame_temp_transactions.transaction_id%length doesn't work here. */
617 end if;
618 if(instrb(dynamicQuery, ame_util2.itemClassPlaceHolder) > 0) then
619 dbms_sql.bind_variable(dynamicCursor,
620 ame_util2.itemClassPlaceHolder,
621 itemClassIn,
622 50); /* ame_temp_transactions.transaction_id%length doesn't work here. */
623 end if;
624 if(instrb(dynamicQuery, ame_util2.itemIdPlaceHolder) > 0) then
625 dbms_sql.bind_variable(dynamicCursor,
626 ame_util2.itemIdPlaceHolder,
627 itemIdIn,
628 50); /* ame_temp_transactions.transaction_id%length doesn't work here. */
629 end if;
630 dbms_sql.define_array(dynamicCursor,
631 1,
632 tempAttributeValues1,
633 ame_util.attributeValueTypeLength,
634 1);
635 rowsFound := dbms_sql.execute(dynamicCursor);
636 loop
637 rowsFound := dbms_sql.fetch_rows(dynamicCursor);
638 dbms_sql.column_value(dynamicCursor,
639 1,
640 tempAttributeValues1);
641 exit when rowsFound < 2;
642 end loop;
643 dbms_sql.close_cursor(dynamicCursor);
644 return(tempAttributeValues1(1));
645 else
646 /* this is not a variant attribute value would have fetched already in
647 fetchAttributeValues return the same */
648 return(engAttributeValues1(engAttributeValueIndexes(attributeIdIn)));
649 end if;
650 exception
651 when others then
652 ame_util.runtimeException(packageNameIn => 'ame_engine',
653 routineNameIn => 'getVariantAttributeValue',
654 exceptionNumberIn => sqlcode,
655 exceptionStringIn => sqlerrm);
656 raise;
657 return null;
658 end getVariantAttributeValue;
659 /* function getVariantAttributeValue2(attributeIdIn in integer,
660 itemClassIn in varchar2,
661 itemIdIn in varchar2) return number as
662 begin
663 return(getVariantAttributeValue(attributeIdIn => attributeIdIn,
664 itemClassIn => itemClassIn,
665 itemIdIn => itemIdIn));
666 exception
667 when others then
668 ame_util.runtimeException(packageNameIn => 'ame_engine',
669 routineNameIn => 'getVariantAttributeValue2',
670 exceptionNumberIn => sqlcode,
671 exceptionStringIn => sqlerrm);
672 raise;
673 return null;
674 end getVariantAttributeValue2;*/
675 function conditionIsSatisfied(conditionIdIn in integer,
676 itemClassIdIn in integer,
677 itemIndexIn in integer) return boolean as
678 attributeId integer;
679 attributeNumberValue number;
680 attributeType ame_attributes.attribute_type%type;
681 attributeTypeException exception;
682 attributeValue1 ame_util.attributeValueType;
683 attributeValue2 ame_util.attributeValueType;
684 attributeValue3 ame_util.attributeValueType;
685 attributeValueDate date;
686 errorCode integer;
687 errorMessage ame_util.longestStringType;
688 headerLevelCondition boolean;
689 includeLowerLimit ame_conditions.include_lower_limit%type;
690 includeUpperLimit ame_conditions.include_upper_limit%type;
691 parameterOne ame_conditions.parameter_one%type;
692 parameterOneDate date;
693 parameterOneNumber number;
694 parameterThree ame_conditions.parameter_three%type;
695 parameterTwo ame_conditions.parameter_two%type;
696 parameterTwoDate date;
697 parameterTwoNumber number;
698 begin
699 /* Check whether the condition is on a header-level attribute. */
700 if(engItemClassNames(engItemClassIndexes(engAttributeItemClassIds(engACAttributeIds(conditionIdIn)))) =
701 ame_util.headerItemClassName) then
702 headerLevelCondition := true;
703 else
704 headerLevelCondition := false;
705 end if;
706 attributeId := engACAttributeIds(conditionIdIn);
707 /* Check for a cached value, for conditions on header-level attributes. */
708 if (headerLevelCondition and
709 not engIsTestTransaction and
710 not engAttributeVariant.exists(attributeId) and
711 engHeaderConditionValues.exists(conditionIdIn)) then
712 /* The value is cached. */
713 if(engHeaderConditionValues(conditionIdIn) = ame_util.booleanTrue) then
714 return(true);
715 end if;
716 return(false);
717 end if;
718 /* The value must be calculated. */
719 attributeType := engAttributeTypes(attributeId);
720 if(attributeType <> ame_util.stringAttributeType) then
721 includeLowerLimit := engACIncludeLowerLimits(conditionIdIn);
722 includeUpperLimit := engACIncludeUpperLimits(conditionIdIn);
723 parameterOne := engACParameterOnes(conditionIdIn);
724 parameterTwo := engACParameterTwos(conditionIdIn);
725 parameterThree := engACParameterThrees(conditionIdIn);
726 end if;
727 if(headerLevelCondition) then
728 if isVariant(attributeId) then
729 attributeValue1 := getVariantAttributeValue
730 (attributeIdIn => attributeId,
731 itemClassIn => getItemClassName(itemClassIdIn => itemClassIdIn),
732 itemIdIn => engItemIds(itemIndexIn));
733 else
734 getHeaderAttValues1(attributeIdIn => attributeId,
735 attributeValue1Out => attributeValue1,
736 attributeValue2Out => attributeValue2,
737 attributeValue3Out => attributeValue3);
738 end if;
739 else
740 getItemAttValues3(attributeIdIn => attributeId,
741 itemIndexIn => itemIndexIn,
742 attributeValue1Out => attributeValue1,
743 attributeValue2Out => attributeValue2,
744 attributeValue3Out => attributeValue3);
745 end if;
746 /* numbers and currencies */
747 if(attributeType = ame_util.numberAttributeType or
748 attributeType = ame_util.currencyAttributeType) then
749 /* First handle the case of a null value. */
750 if(attributeValue1 is null) then
751 if(parameterOne is null and
752 parameterTwo is null) then
753 if(headerLevelCondition) then
754 engHeaderConditionValues(conditionIdIn) := ame_util.booleanTrue;
755 end if;
756 return(true);
757 else
758 if(headerLevelCondition) then
759 engHeaderConditionValues(conditionIdIn) := ame_util.booleanFalse;
760 end if;
761 return(false);
762 end if;
763 end if;
764 /* Now handle the other cases. */
765 if(attributeType = ame_util.currencyAttributeType and
766 /* Issue 6 of the Bug list bug (4094080) */
767 /* modified form parameterThree <> attributeValue3 to */
768 /* parameterThree <> attributeValue2 */
769 parameterThree <> attributeValue2) then
770 attributeNumberValue :=
771 ame_util.convertCurrency(fromCurrencyCodeIn => attributeValue2,
772 toCurrencyCodeIn => parameterThree,
773 conversionTypeIn => attributeValue3,
774 amountIn => fnd_number.canonical_to_number(canonical => attributeValue1),
775 dateIn => engEffectiveRuleDate,
776 applicationIdIn => engAmeApplicationId);
777 else
778 attributeNumberValue := fnd_number.canonical_to_number(canonical => attributeValue1);
779 end if;
780 parameterOneNumber := fnd_number.canonical_to_number(canonical => parameterOne);
781 parameterTwoNumber := fnd_number.canonical_to_number(canonical => parameterTwo);
782 if(includeLowerLimit = ame_util.booleanTrue and
783 attributeNumberValue = parameterOneNumber) then
784 if(headerLevelCondition) then
785 engHeaderConditionValues(conditionIdIn) := ame_util.booleanTrue;
786 end if;
787 return(true);
788 end if;
789 if(includeUpperLimit = ame_util.booleanTrue and
790 attributeNumberValue = parameterTwoNumber) then
791 if(headerLevelCondition) then
792 engHeaderConditionValues(conditionIdIn) := ame_util.booleanTrue;
793 end if;
794 return(true);
795 end if;
796 if((parameterOneNumber is null and attributeNumberValue < parameterTwoNumber) or
797 (parameterOneNumber < attributeNumberValue and parameterTwoNumber is null) or
798 (parameterOneNumber < attributeNumberValue and attributeNumberValue < parameterTwoNumber)) then
799 if(headerLevelCondition) then
800 engHeaderConditionValues(conditionIdIn) := ame_util.booleanTrue;
801 end if;
802 return(true);
803 end if;
804 /* dates */
805 elsif(attributeType = ame_util.dateAttributeType) then
806 attributeValueDate := ame_util.versionStringToDate(stringDateIn => attributeValue1);
807 parameterOneDate := ame_util.versionStringToDate(stringDateIn => parameterOne);
808 parameterTwoDate := ame_util.versionStringToDate(stringDateIn => parameterTwo);
809 /* First handle the case of a null value. */
810 if(attributeValue1 is null) then
811 if(parameterOne is null and
812 parameterTwo is null) then
813 if(headerLevelCondition) then
814 engHeaderConditionValues(conditionIdIn) := ame_util.booleanTrue;
815 end if;
816 return(true);
817 else
818 if(headerLevelCondition) then
819 engHeaderConditionValues(conditionIdIn) := ame_util.booleanFalse;
820 end if;
821 return(false);
822 end if;
823 end if;
824 /* Now handle the other cases. */
825 if(includeLowerLimit = ame_util.booleanTrue and
826 attributeValueDate = parameterOneDate) then
827 if(headerLevelCondition) then
828 engHeaderConditionValues(conditionIdIn) := ame_util.booleanTrue;
829 end if;
830 return(true);
831 end if;
832 if(includeUpperLimit = ame_util.booleanTrue and
833 attributeValueDate = parameterTwoDate) then
834 if(headerLevelCondition) then
835 engHeaderConditionValues(conditionIdIn) := ame_util.booleanTrue;
836 end if;
837 return(true);
838 end if;
839 if((parameterOneDate is null and attributeValueDate < parameterTwoDate) or
840 (parameterOneDate < attributeValueDate and parameterTwoDate is null) or
841 (parameterOneDate < attributeValueDate and attributeValueDate < parameterTwoDate)) then
842 if(headerLevelCondition) then
843 engHeaderConditionValues(conditionIdIn) := ame_util.booleanTrue;
844 end if;
845 return(true);
846 end if;
847 /* booleans */
848 elsif(attributeType = ame_util.booleanAttributeType) then
849 if((attributeValue1 is null and
850 parameterOne is null) or
851 attributeValue1 = parameterOne) then
852 if(headerLevelCondition) then
853 engHeaderConditionValues(conditionIdIn) := ame_util.booleanTrue;
854 end if;
855 return(true); /* If both pseudo-booleans are null, the condition applies. */
856 end if;
857 return(false);
858 /* strings */
859 elsif(attributeType = ame_util.stringAttributeType) then
860 /* Note that if the attribute value and a string value are both null, the condition applies. */
861 for stringValueIndex in
862 engACStringValueFirstIndexes(conditionIdIn) ..
863 (engACStringValueFirstIndexes(conditionIdIn) + engACStringValueCounts(conditionIdIn) - 1) loop
864 if((attributeValue1 is null and engACStringValues(stringValueIndex) is null) or
865 attributeValue1 = engACStringValues(stringValueIndex)) then
866 if(headerLevelCondition) then
867 engHeaderConditionValues(conditionIdIn) := ame_util.booleanTrue;
868 end if;
869 return(true);
870 end if;
871 end loop;
872 else
873 raise attributeTypeException;
874 end if;
875 /* The condition is not satisfied. */
876 if(headerLevelCondition) then
877 engHeaderConditionValues(conditionIdIn) := ame_util.booleanFalse;
878 end if;
879 return(false);
880 exception
881 when attributeTypeException then
882 errorCode := -20001;
883 errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
884 messageNameIn => 'AME_400113_ENG_ATTR_UNREG_TYPE');
885 ame_util.runtimeException(packageNameIn => 'ame_engine',
886 routineNameIn => 'conditionIsSatisfied',
887 exceptionNumberIn => errorCode,
888 exceptionStringIn => errorMessage);
889 raise_application_error(errorCode,
890 errorMessage);
891 return(null);
892 when others then
893 ame_util.runtimeException(packageNameIn => 'ame_engine',
894 routineNameIn => 'conditionIsSatisfied',
895 exceptionNumberIn => sqlcode,
896 exceptionStringIn => sqlerrm);
897 raise;
898 return(null);
899 end conditionIsSatisfied;
900 function evalPrioritiesPerItem return boolean as
901 begin
902 return(engEvalPrioritiesPerItem);
903 exception
904 when others then
905 ame_util.runtimeException(packageNameIn => 'ame_engine',
906 routineNameIn => 'evalPrioritiesPerItem',
907 exceptionNumberIn => sqlcode,
908 exceptionStringIn => sqlerrm);
909 raise;
910 return(null);
911 end evalPrioritiesPerItem;
912 function insertionExists(orderTypeIn in varchar2,
913 parameterIn in varchar2) return boolean as
914 begin
915 for i in 1 .. engInsertionOrderTypeList.count loop
916 if(engInsertionOrderTypeList(i) = orderTypeIn and
917 engInsertionParameterList(i) = parameterIn) then
918 return(true);
919 end if;
920 end loop;
921 return(false);
922 exception
923 when others then
924 ame_util.runtimeException(packageNameIn => 'ame_engine',
925 routineNameIn => 'insertionExists',
926 exceptionNumberIn => sqlcode,
927 exceptionStringIn => sqlerrm);
928 raise;
929 return(null);
930 end insertionExists;
931 function isLocalTransaction return boolean as
932 begin
933 return(engIsLocalTransaction);
934 exception
935 when others then
936 ame_util.runtimeException(packageNameIn => 'ame_engine',
937 routineNameIn => 'isLocalTransaction',
938 exceptionNumberIn => sqlcode,
939 exceptionStringIn => sqlerrm);
940 raise;
941 return(null);
942 end isLocalTransaction;
943 function isStaticAttUsage(attributeIdIn in integer) return boolean as
944 begin
945 if(engAttributeIsStatics(attributeIdIn) = ame_util.booleanTrue) then
946 return(true);
947 end if;
948 return(false);
949 exception
950 when others then
951 ame_util.runtimeException(packageNameIn => 'ame_engine',
952 routineNameIn => 'isStaticAttUsage',
953 exceptionNumberIn => sqlcode,
954 exceptionStringIn => sqlerrm);
955 raise;
956 return(false);
957 end isStaticAttUsage;
958 function isTestTransaction return boolean as
959 begin
960 return(engIsTestTransaction);
961 exception
962 when others then
963 ame_util.runtimeException(packageNameIn => 'ame_engine',
964 routineNameIn => 'isTestTransaction',
965 exceptionNumberIn => sqlcode,
966 exceptionStringIn => sqlerrm);
967 raise;
968 return(null);
969 end isTestTransaction;
970 function isVariant(attributeIdIn in integer) return boolean as
971 begin
972 if checkAttributeVariant(attributeIdIn) = ame_util.booleanTrue then
973 if engIsTestTransaction then
974 return true;
975 elsif engAttributeVariant.exists(attributeIdIn) then
976 return true;
977 end if;
978 end if;
979 return false;
980 exception
981 when others then
982 ame_util.runtimeException(packageNameIn => 'ame_engine',
983 routineNameIn => 'isVariant',
984 exceptionNumberIn => sqlcode,
985 exceptionStringIn => sqlerrm);
986 raise;
987 return(null);
988 end isVariant;
989 function processPriorities return boolean as
990 begin
991 return(engProcessPriorities);
992 exception
993 when others then
994 ame_util.runtimeException(packageNameIn => 'ame_engine',
995 routineNameIn => 'processPriorities',
996 exceptionNumberIn => sqlcode,
997 exceptionStringIn => sqlerrm);
998 raise;
999 return(null);
1000 end processPriorities;
1001 function processProductionActions return boolean as
1002 begin
1003 return(engProcessProductionActions);
1004 exception
1005 when others then
1006 ame_util.runtimeException(packageNameIn => 'ame_engine',
1007 routineNameIn => 'processProductionActions',
1008 exceptionNumberIn => sqlcode,
1009 exceptionStringIn => sqlerrm);
1010 raise;
1011 return(null);
1012 end processProductionActions;
1013 function processProductionRules return boolean as
1014 begin
1015 return(engProcessProductionRules);
1016 exception
1017 when others then
1018 ame_util.runtimeException(packageNameIn => 'ame_engine',
1019 routineNameIn => 'processProductionRules',
1020 exceptionNumberIn => sqlcode,
1021 exceptionStringIn => sqlerrm);
1022 raise;
1023 return(null);
1024 end processProductionRules;
1025 /********************************* fetch functions **********************************/
1026 function fetchAmeApplicationId(fndApplicationIdIn in integer,
1027 transactionTypeIdIn in varchar2 default null) return integer as
1028 ameApplicationId integer;
1029 begin
1030 select application_id
1031 into ameApplicationId
1032 from ame_calling_apps
1033 where
1034 fnd_application_id = fndApplicationIdIn and
1035 ((transactionTypeIdIn is null and transaction_type_id is null) or
1036 (transaction_type_id = transactionTypeIdIn)) and
1037 /* Don't use engEffectiveRuleDate here. */
1038 sysdate between
1039 start_date and
1040 nvl(end_date - ame_util.oneSecond, sysdate) and
1041 rownum < 2; /* Avoids second fetch otherwise required by ANSI standard to check for too many rows. */
1042 return(ameApplicationId);
1043 exception
1044 when others then
1045 ame_util.runtimeException(packageNameIn => 'ame_engine',
1046 routineNameIn => 'fetchAmeApplicationId',
1047 exceptionNumberIn => sqlcode,
1048 exceptionStringIn => sqlerrm);
1049 raise;
1050 return(null);
1051 end fetchAmeApplicationId;
1052 /********************************** get functions ***********************************/
1053 function getActionTypeChainOrderMode(actionTypeIdIn in integer) return varchar2 as
1054 begin
1055 return(engActionTypeChainOrderModes(actionTypeIdIn));
1056 exception
1057 when others then
1058 ame_util.runtimeException(packageNameIn => 'ame_engine',
1059 routineNameIn => 'getActionTypeChainOrderMode',
1060 exceptionNumberIn => sqlcode,
1061 exceptionStringIn => sqlerrm);
1062 raise;
1063 return(null);
1064 end getActionTypeChainOrderMode;
1065 function getActionTypeId(actionTypeNameIn in varchar2) return integer as
1066 tempIndex integer;
1067 begin
1068 tempIndex := engActionTypeNames.first;
1069 while(tempIndex is not null) loop
1070 if(engActionTypeNames(tempIndex) = actionTypeNameIn) then
1071 return(tempIndex);
1072 end if;
1073 tempIndex := engActionTypeNames.next(tempIndex);
1074 end loop;
1075 return(null);
1076 exception
1077 when others then
1078 ame_util.runtimeException(packageNameIn => 'ame_engine',
1079 routineNameIn => 'getActionTypeId',
1080 exceptionNumberIn => sqlcode,
1081 exceptionStringIn => sqlerrm);
1082 raise;
1083 return(null);
1084 end getActionTypeId;
1085 function getActionTypeName(actionTypeIdIn in integer) return varchar2 as
1086 begin
1087 if(actionTypeIdIn = ame_util.nullInsertionActionTypeId or actionTypeIdIn = -2 ) then
1088 return(null);
1089 end if;
1090 return(engActionTypeNames(actionTypeIdIn));
1091 exception
1092 when others then
1093 ame_util.runtimeException(packageNameIn => 'ame_engine',
1094 routineNameIn => 'getActionTypeName',
1095 exceptionNumberIn => sqlcode,
1096 exceptionStringIn => sqlerrm);
1097 raise;
1098 return(null);
1099 end getActionTypeName;
1100 function getActionTypeOrderNumber(actionTypeIdIn in integer) return integer as
1101 begin
1102 return(engActionTypeOrderNumbers(actionTypeIdIn));
1103 exception
1104 when others then
1105 ame_util.runtimeException(packageNameIn => 'ame_engine',
1106 routineNameIn => 'getActionTypeOrderNumber',
1107 exceptionNumberIn => sqlcode,
1108 exceptionStringIn => sqlerrm);
1109 raise;
1110 return(null);
1111 end getActionTypeOrderNumber;
1112 function getActionTypePackageName(actionTypeIdIn in integer) return varchar2 as
1113 begin
1114 return(engActionTypePackageNames(actionTypeIdIn));
1115 exception
1116 when others then
1117 ame_util.runtimeException(packageNameIn => 'ame_engine',
1118 routineNameIn => 'getActionTypePackageName',
1119 exceptionNumberIn => sqlcode,
1120 exceptionStringIn => sqlerrm);
1121 raise;
1122 return(null);
1123 end getActionTypePackageName;
1124 function getActionTypeUsage(actionTypeIdIn in integer) return integer as
1125 begin /* getActionTypeUsage returns the rule type that uses the input action type. */
1126 return(engActionTypeUsages(actionTypeIdIn));
1127 exception
1128 when others then
1129 ame_util.runtimeException(packageNameIn => 'ame_engine',
1130 routineNameIn => 'getActionTypeUsage',
1131 exceptionNumberIn => sqlcode,
1132 exceptionStringIn => sqlerrm);
1133 raise;
1134 return(null);
1135 end getActionTypeUsage;
1136 function getActionTypeVotingRegime(actionTypeIdIn in integer) return varchar2 as
1137 begin
1138 if(actionTypeIdIn = ame_util.nullInsertionActionTypeId or actionTypeIdIn = -2 ) then
1139 return(null);
1140 end if;
1141 return(engActionTypeVotingRegimes(actionTypeIdIn));
1142 exception
1143 when others then
1144 ame_util.runtimeException(packageNameIn => 'ame_engine',
1145 routineNameIn => 'getActionTypeVotingRegime',
1146 exceptionNumberIn => sqlcode,
1147 exceptionStringIn => sqlerrm);
1148 raise;
1149 return(null);
1150 end getActionTypeVotingRegime;
1151 function getAmeApplicationId return integer as
1152 begin
1153 return(engAmeApplicationId);
1154 exception
1155 when others then
1156 ame_util.runtimeException(packageNameIn => 'ame_engine',
1157 routineNameIn => 'getAmeApplicationId',
1158 exceptionNumberIn => sqlcode,
1159 exceptionStringIn => sqlerrm);
1160 raise;
1161 return(null);
1162 end getAmeApplicationId;
1163 function getApprovalProcessCompleteYN return varchar2 as
1164 begin
1165 return(engStApprovalProcessCompleteYN);
1166 exception
1167 when others then
1168 ame_util.runtimeException(packageNameIn => 'ame_engine',
1169 routineNameIn => 'getApprovalProcessCompleteYN',
1170 exceptionNumberIn => sqlcode,
1171 exceptionStringIn => sqlerrm);
1172 raise;
1173 return(null);
1174 end getApprovalProcessCompleteYN;
1175 function getAttributeIdByName(attributeNameIn in varchar2) return integer as
1176 errorCode integer;
1177 errorMessage ame_util.longestStringType;
1178 notFoundException exception;
1179 tempIndex integer;
1180 begin
1181 tempIndex := engAttributeNames.first;
1182 loop
1183 if(tempIndex is null) then
1184 raise notFoundException;
1185 end if;
1186 if(engAttributeNames(tempIndex) = attributeNameIn) then
1187 return(tempIndex);
1188 end if;
1189 tempIndex := engAttributeNames.next(tempIndex);
1190 end loop;
1191 exception
1192 when notFoundException then
1193 errorCode := -20001;
1194 errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
1195 messageNameIn => 'AME_400680_NO_ID_FOR_ATTR',
1196 tokenNameOneIn => 'ATTRIBUTE_NAME',
1197 tokenValueOneIn => attributeNameIn);
1198 ame_util.runtimeException(packageNameIn => 'ame_engine',
1199 routineNameIn => 'getAttributeIdByName',
1200 exceptionNumberIn => errorCode,
1201 exceptionStringIn => errorMessage);
1202 raise_application_error(errorCode, errorMessage);
1203 return(null);
1204 when others then
1205 ame_util.runtimeException(packageNameIn => 'ame_engine',
1206 routineNameIn => 'getAttributeIdByName',
1207 exceptionNumberIn => sqlcode,
1208 exceptionStringIn => attributeNameIn || ': ' || sqlerrm);
1209 raise;
1210 return(null);
1211 end getAttributeIdByName;
1212 function getAttributeName(attributeIdIn in integer) return varchar2 as
1213 begin
1214 return(engAttributeNames(attributeIdIn));
1215 exception
1216 when others then
1217 ame_util.runtimeException(packageNameIn => 'ame_engine',
1218 routineNameIn => 'getAttributeName',
1219 exceptionNumberIn => sqlcode,
1220 exceptionStringIn => sqlerrm);
1221 raise;
1222 return(null);
1223 end getAttributeName;
1224 function getAttributeType(attributeIdIn in integer) return varchar2 as
1225 begin
1226 return(engAttributeTypes(attributeIdIn));
1227 exception
1228 when others then
1229 ame_util.runtimeException(packageNameIn => 'ame_engine',
1230 routineNameIn => 'getAttributeType',
1231 exceptionNumberIn => sqlcode,
1232 exceptionStringIn => sqlerrm);
1233 raise;
1234 return(null);
1235 end getAttributeType;
1236 function getConfigVarValue(configVarNameIn in varchar2) return varchar2 as
1237 errorCode integer;
1238 errorMessage ame_util.longestStringType;
1239 noValueException exception;
1240 begin
1241 for i in 1 .. engConfigVarNames.count loop
1242 if(engConfigVarNames(i) = configVarNameIn) then
1243 return(engConfigVarValues(i));
1244 end if;
1245 end loop;
1246 raise noValueException;
1247 exception
1248 when noValueException then
1249 errorCode := -20001;
1250 errorMessage := ame_util.getMessage(applicationShortNameIn => 'PER',
1251 messageNameIn => 'AME_400114_ENG_INV_CON_VAR',
1252 tokenNameOneIn => 'CONFIG_VAR',
1253 tokenValueOneIn => configVarNameIn);
1254 ame_util.runtimeException(packageNameIn => 'ame_engine',
1255 routineNameIn => 'getConfigVarValue',
1256 exceptionNumberIn => errorCode,
1257 exceptionStringIn => errorMessage);
1258 raise_application_error(errorCode,
1259 errorMessage);
1260 when others then
1261 ame_util.runtimeException(packageNameIn => 'ame_engine',
1262 routineNameIn => 'getConfigVarValue',
1263 exceptionNumberIn => sqlcode,
1264 exceptionStringIn => sqlerrm);
1265 raise;
1266 return(null);
1267 end getConfigVarValue;
1268 function getEffectiveRuleDate return date as
1269 begin
1270 return(engEffectiveRuleDate);
1271 exception
1272 when others then
1273 ame_util.runtimeException(packageNameIn => 'ame_engine',
1274 routineNameIn => 'getEffectiveRuleDate',
1275 exceptionNumberIn => sqlcode,
1276 exceptionStringIn => sqlerrm);
1277 raise;
1278 return(null);
1279 end getEffectiveRuleDate;
1280 function getFndApplicationId return integer as
1281 begin
1282 return(engFndApplicationId);
1283 exception
1284 when others then
1285 ame_util.runtimeException(packageNameIn => 'ame_engine',
1286 routineNameIn => 'getFndApplicationId',
1287 exceptionNumberIn => sqlcode,
1288 exceptionStringIn => sqlerrm);
1289 raise;
1290 return(null);
1291 end getFndApplicationId;
1292 function getForwardingBehavior(forwarderTypeIn in varchar2,
1293 forwardeeTypeIn in varchar2,
1294 approvalStatusIn in varchar2) return varchar2 as
1295 errorCode integer;
1296 errorMessage ame_util.longestStringType;
1297 badArgsException exception;
1298 begin
1299 if(forwarderTypeIn = ame_util.chainOfAuthorityForwarder) then
1300 if(forwardeeTypeIn = ame_util.previousSameChainForwardee) then
1301 if(approvalStatusIn = ame_util.forwardStatus) then
1302 return(engForwardingBehaviors(1));
1303 elsif(approvalStatusIn = ame_util.approveAndForwardStatus) then
1304 return(engForwardingBehaviors(2));
1305 end if;
1306 elsif(forwardeeTypeIn = ame_util.subordSameHierarchyForwardee) then
1307 if(approvalStatusIn = ame_util.forwardStatus) then
1308 return(engForwardingBehaviors(3));
1309 elsif(approvalStatusIn = ame_util.approveAndForwardStatus) then
1310 return(engForwardingBehaviors(4));
1311 end if;
1312 elsif(forwardeeTypeIn = ame_util.alreadyInListForwardee) then
1313 if(approvalStatusIn = ame_util.forwardStatus) then
1314 return(engForwardingBehaviors(5));
1315 elsif(approvalStatusIn = ame_util.approveAndForwardStatus) then
1316 return(engForwardingBehaviors(6));
1317 end if;
1318 end if;
1319 elsif(forwarderTypeIn = ame_util.adHocForwarder) then
1320 if(forwardeeTypein = ame_util.alreadyInListForwardee) then
1321 if(approvalStatusIn = ame_util.forwardStatus) then
1322 return(engForwardingBehaviors(7));
1323 elsif(approvalStatusIn = ame_util.approveAndForwardStatus) then
1324 return(engForwardingBehaviors(8));
1325 end if;
1326 end if;
1327 end if;
1328 raise badArgsException;
1329 exception
1330 when badArgsException then
1331 errorCode := -20001;
1332 errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
1333 messageNameIn => 'AME_400115_ENG_INV_VAL_ARG');
1334 ame_util.runtimeException(packageNameIn => 'ame_engine',
1335 routineNameIn => 'getForwardingBehavior',
1336 exceptionNumberIn => errorCode,
1337 exceptionStringIn => errorMessage);
1338 raise_application_error(errorCode,
1339 errorMessage);
1340 return(null);
1341 when others then
1342 ame_util.runtimeException(packageNameIn => 'ame_engine',
1343 routineNameIn => 'getForwardingBehavior',
1344 exceptionNumberIn => sqlcode,
1345 exceptionStringIn => sqlerrm);
1346 raise;
1347 return(null);
1348 end getForwardingBehavior;
1349 function getHandlerActionTypeId return integer as
1350 begin
1351 return(engAppActionTypeIds(engAppHandlerFirstIndex));
1352 exception
1353 when others then
1354 ame_util.runtimeException(packageNameIn => 'ame_engine',
1355 routineNameIn => 'getHandlerActionTypeId',
1356 exceptionNumberIn => sqlcode,
1357 exceptionStringIn => sqlerrm);
1358 raise;
1359 return(null);
1360 end getHandlerActionTypeId;
1361 function getHandlerActionTypeOrderNum return integer as
1362 begin
1363 return(engActionTypeOrderNumbers(engAppActionTypeIds(engAppHandlerFirstIndex)));
1364 exception
1365 when others then
1366 ame_util.runtimeException(packageNameIn => 'ame_engine',
1367 routineNameIn => 'getHandlerActionTypeOrderNum',
1368 exceptionNumberIn => sqlcode,
1369 exceptionStringIn => sqlerrm);
1370 raise;
1371 return(null);
1372 end getHandlerActionTypeOrderNum;
1373 function getHandlerApprovalStatus(approverIn in ame_util.approverRecord2,
1374 votingRegimeIn in varchar2 default null,
1375 isInsertionapprover in boolean default false) return varchar2 as
1376 l_approvalStatus varchar2(50);
1377 l_action_type_id number;
1378 l_votingRegime varchar2(100);
1379 l_action_type_name varchar2(100);
1380 begin
1381 for i in 1..engOldApproverList.count loop
1382 if(approversMatch(approverRecord1In => approverIn,
1383 approverRecord2In => engOldApproverList(i))) then
1384 l_approvalStatus := engOldApproverList(i).approval_status;
1385 end if;
1386 end loop;
1387 if l_approvalStatus is null and (approverIn.action_type_id <> ame_util.nullInsertionActionTypeId and
1388 approverIn.action_type_id is not null) and
1389 not isInsertionapprover then
1390 l_action_type_id := approverIn.action_type_id;
1391 l_action_type_name := getActionTypeName(l_action_type_id);
1392 if l_action_type_name not in (ame_util.postApprovalTypeName,ame_util.preApprovalTypeName ) then
1393 l_votingRegime := ame_engine.getActionTypeVotingRegime(actionTypeIdIn => approverIn.action_type_id);
1394 else
1395 l_votingRegime := votingRegimeIn;
1396 end if;
1397 if l_votingRegime = ame_util.firstApproverVoting then
1398 for i in 1..engOldApproverList.count loop
1399 if approverIn.name <> engOldApproverList(i).name and
1400 approverIn.action_type_id = engOldApproverList(i).action_type_id and
1401 approverIn.group_or_chain_id = engOldApproverList(i).group_or_chain_id and
1402 approverIn.item_class = engOldApproverList(i).item_class and
1403 approverIn.item_id = engOldApproverList(i).item_id and
1404 engOldApproverList(i).api_insertion <> ame_util.apiInsertion and
1405 engOldApproverList(i).approval_status in (ame_util.approvedStatus
1406 ,ame_util.beatByFirstResponderStatus
1407 ,ame_util.rejectStatus ) then
1408 return(ame_util.beatByFirstResponderStatus);
1409 end if;
1410 end loop;
1411 end if;
1412 return(l_approvalStatus);
1413 else
1414 return(l_approvalStatus);
1415 end if;
1416 return(null);
1417 exception
1418 when others then
1419 ame_util.runtimeException(packageNameIn => 'ame_engine',
1420 routineNameIn => 'getHandlerApprovalStatus',
1421 exceptionNumberIn => sqlcode,
1422 exceptionStringIn => sqlerrm);
1423 raise;
1424 return(null);
1425 end getHandlerApprovalStatus;
1426 function getHandlerAuthority return varchar2 as
1427 errorCode integer;
1428 errorMessage ame_util.longestStringType;
1429 badRuleTypeException exception;
1430 ruleType integer;
1431 begin
1432 ruleType := getHandlerRuleType;
1433 if(ruleType = ame_util.preListGroupRuleType) then
1434 return(ame_util.preApprover);
1435 elsif(ruleType = ame_util.postListGroupRuleType) then
1436 return(ame_util.postApprover);
1437 elsif(ruleType = ame_util.authorityRuleType) then
1438 return(ame_util.authorityApprover);
1439 else
1440 raise badRuleTypeException;
1441 end if;
1442 exception
1443 when badRuleTypeException then
1444 errorCode := -20001;
1445 errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
1446 messageNameIn => 'AME_400681_INV_HANDLER_RUL_TYP');
1447 ame_util.runtimeException(packageNameIn => 'ame_engine',
1448 routineNameIn => 'getHandlerAuthority',
1449 exceptionNumberIn => errorCode,
1450 exceptionStringIn => errorMessage);
1451 raise_application_error(errorCode,
1452 errorMessage);
1453 return(null);
1454 when others then
1455 ame_util.runtimeException(packageNameIn => 'ame_engine',
1456 routineNameIn => 'getHandlerAuthority',
1457 exceptionNumberIn => sqlcode,
1458 exceptionStringIn => sqlerrm);
1459 raise;
1460 return(null);
1461 end getHandlerAuthority;
1462 function getHandlerItemClassId return integer as
1463 begin
1464 return(engAppRuleItemClassIds(engAppHandlerFirstIndex));
1465 exception
1466 when others then
1467 ame_util.runtimeException(packageNameIn => 'ame_engine',
1468 routineNameIn => 'getHandlerItemClassId',
1469 exceptionNumberIn => sqlcode,
1470 exceptionStringIn => sqlerrm);
1471 raise;
1472 return(null);
1473 end getHandlerItemClassId;
1474 function getHandlerItemClassName return varchar2 as
1475 begin
1476 return(getItemClassName(itemClassIdIn => engAppRuleItemClassIds(engAppHandlerFirstIndex)));
1477 exception
1478 when others then
1479 ame_util.runtimeException(packageNameIn => 'ame_engine',
1480 routineNameIn => 'getHandlerItemClassName',
1481 exceptionNumberIn => sqlcode,
1482 exceptionStringIn => sqlerrm);
1483 raise;
1484 return(null);
1485 end getHandlerItemClassName;
1486 function getHandlerItemClassOrderNumber return integer as
1487 begin
1488 return(engItemClassOrderNumbers(engItemClassIndexes(engAppRuleItemClassIds(engAppHandlerFirstIndex))));
1489 exception
1490 when others then
1491 ame_util.runtimeException(packageNameIn => 'ame_engine',
1492 routineNameIn => 'getHandlerItemClassOrderNumber',
1493 exceptionNumberIn => sqlcode,
1494 exceptionStringIn => sqlerrm);
1495 raise;
1496 return(null);
1497 end getHandlerItemClassOrderNumber;
1498 function getHandlerItemId return varchar2 as
1499 begin
1500 return(engAppAppItemIds(engAppHandlerFirstIndex));
1501 exception
1502 when others then
1503 ame_util.runtimeException(packageNameIn => 'ame_engine',
1504 routineNameIn => 'getHandlerItemId',
1505 exceptionNumberIn => sqlcode,
1506 exceptionStringIn => sqlerrm);
1507 raise;
1508 return(null);
1509 end getHandlerItemId;
1510 function getHandlerItemOrderNumber return integer as
1511 begin
1512 if(getItemClassParMode(itemClassIdIn => engAppRuleItemClassIds(engAppHandlerFirstIndex)) =
1513 ame_util.parallelItems) then
1514 return(1);
1515 else /* The parallelization modes is ame_util.serialItems. */
1516 return(1 + getItemOffset(itemClassIdIn => engAppRuleItemClassIds(engAppHandlerFirstIndex),
1517 itemIdIn => engAppAppItemIds(engAppHandlerFirstIndex)));
1518 end if;
1519 exception
1520 when others then
1521 ame_util.runtimeException(packageNameIn => 'ame_engine',
1522 routineNameIn => 'getHandlerItemOrderNumber',
1523 exceptionNumberIn => sqlcode,
1524 exceptionStringIn => sqlerrm);
1525 raise;
1526 return(null);
1527 end getHandlerItemOrderNumber;
1528 function getHandlerOccurrence(nameIn in varchar2,
1529 itemClassIn in varchar2 default null,
1530 itemIdIn in varchar2 default null,
1531 actionTypeIdIn in integer default null,
1532 groupOrChainIdIn in integer default null) return integer as
1533 engStApproversCount integer;
1534 itemClass ame_temp_old_approver_lists.item_class%type;
1535 itemId ame_temp_old_approver_lists.item_id%type;
1536 actionTypeId integer;
1537 groupOrChainId integer;
1538 occurrence integer;
1539 begin
1540 engStApproversCount := engStApprovers.count;
1541 /* Handle the empty-list case first. */
1542 if(engStApproversCount = 0) then
1543 return(1);
1544 end if;
1545 /* Determine which chain of authority to match. */
1546 if(itemClassIn is null or
1547 itemIdIn is null or
1548 actionTypeIdIn is null or
1549 groupOrChainIdIn is null) then
1550 /*
1551 If we're not trying to match an inserted approver with nullInsertionActionTypeId and
1552 nullInsertionGroupOrChainId, and one of the input arguments is null, match the most
1553 recently added group or chain.
1554 */
1555 for i in reverse 1 .. engStApproversCount loop
1556 if(engStApprovers(i).action_type_id <> ame_util.nullInsertionActionTypeId and
1557 engStApprovers(i).group_or_chain_id <> ame_util.nullInsertionGroupOrChainId and
1558 engStApprovers(i).item_class is not null and
1559 engStApprovers(i).item_id is not null and
1560 engStApprovers(i).action_type_id is not null and
1561 engStApprovers(i).group_or_chain_id is not null) then
1562 itemClass := engStApprovers(i).item_class;
1563 itemId := engStApprovers(i).item_id;
1564 actionTypeId := engStApprovers(i).action_type_id;
1565 groupOrChainId := engStApprovers(i).group_or_chain_id;
1566 exit;
1567 end if;
1568 end loop;
1569 else
1570 itemClass := itemClassIn;
1571 itemId := itemIdIn;
1572 actionTypeId := actionTypeIdIn;
1573 groupOrChainId := groupOrChainIdIn;
1574 end if;
1575 if(itemClass is null) then
1576 /*
1577 One of the input arguments is null, and all approvers in the list have nullInsertionActionTypeId and
1578 nullInsertionGroupOrChainId. So these are the only action-type ID and group-or-chain ID we can match.
1579 In this case, match the item class and item ID of the most recent insertion.
1580 */
1581 itemClass := engStApprovers(engStApproversCount).item_class;
1582 itemId := engStApprovers(engStApproversCount).item_id;
1583 actionTypeId := engStApprovers(engStApproversCount).action_type_id;
1584 groupOrChainId := engStApprovers(engStApproversCount).group_or_chain_id;
1585 end if;
1586 /* Now count matches within the target item class, item ID, action-type ID, and group-or-chain ID. */
1587 occurrence := 1;
1588 for i in 1 .. engStApproversCount loop
1589 /*
1590 The order of the comparisons in the if statement below is significant for efficiency.
1591 (Most of the time, the names won't match, and that ends the comparison for engStApprovers(i).)
1592 (We could stop the comparison upon leaving the target item's approver list, but this would
1593 generally take more work than it would save.)
1594 */
1595 if(engStApprovers(i).name = nameIn and
1596 engStApprovers(i).group_or_chain_id = groupOrChainId and
1597 engStApprovers(i).action_type_id = actionTypeId and
1598 engStApprovers(i).item_id = itemId and
1599 engStApprovers(i).item_class = itemClass) then
1600 occurrence := occurrence + 1;
1601 end if;
1602 end loop;
1603 return(occurrence);
1604 exception
1605 when others then
1606 ame_util.runtimeException(packageNameIn => 'ame_engine',
1607 routineNameIn => 'getHandlerOccurrence',
1608 exceptionNumberIn => sqlcode,
1609 exceptionStringIn => sqlerrm);
1610 raise;
1611 return(null);
1612 end getHandlerOccurrence;
1613 function getHandlerRuleType return integer as
1614 begin
1615 return(engAppRuleTypes(engAppHandlerFirstIndex));
1616 exception
1617 when others then
1618 ame_util.runtimeException(packageNameIn => 'ame_engine',
1619 routineNameIn => 'getHandlerRuleType',
1620 exceptionNumberIn => sqlcode,
1621 exceptionStringIn => sqlerrm);
1622 raise;
1623 return(null);
1624 end getHandlerRuleType;
1625 function getHandlerState(handlerNameIn in varchar2,
1626 parameterIn in varchar2 default null) return varchar2 as
1627 handlerName ame_temp_handler_states.handler_name%type;
1628 tempState ame_temp_handler_states.state%type;
1629 begin
1630 handlerName := upper(handlerNameIn);
1631 select state
1632 into tempState
1633 from ame_temp_handler_states
1634 where
1635 handler_name = handlerName and
1636 ((application_id is null and engAmeApplicationId is null) or
1637 (application_id = engAmeApplicationId)) and
1638 ((parameter is null and parameterIn is null) or
1639 (parameter = parameterIn)) and
1640 rownum < 2; /* Avoids second fetch otherwise required by ANSI standard to check for too many rows. */
1641 return(tempState);
1642 exception
1643 when no_data_found then
1644 return(null);
1645 when others then
1646 ame_util.runtimeException(packageNameIn => 'ame_engine',
1647 routineNameIn => 'getHandlerState',
1648 exceptionNumberIn => sqlcode,
1649 exceptionStringIn => sqlerrm);
1650 raise;
1651 return(null);
1652 end getHandlerState;
1653 function getHandlerSublistOrderNum return integer as
1654 handlerAuthority ame_util.charType;
1655 itemClassSublistMode ame_util.charType;
1656 begin
1657 handlerAuthority := getHandlerAuthority;
1658 itemClassSublistMode := getItemClassSublistMode(itemClassIdIn => engAppRuleItemClassIds(engAppHandlerFirstIndex));
1659 if(itemClassSublistMode = ame_util.serialSublists) then
1660 if(handlerAuthority = ame_util.preApprover) then
1661 return(1);
1662 elsif(handlerAuthority = ame_util.authorityApprover) then
1663 return(2);
1664 else
1665 return(3);
1666 end if;
1667 elsif(itemClassSublistMode = ame_util.parallelSublists) then
1668 return(1);
1669 elsif(itemClassSublistMode = ame_util.preFirst) then
1670 if(handlerAuthority = ame_util.preApprover) then
1671 return(1);
1672 else
1673 return(2);
1674 end if;
1675 else
1676 if(handlerAuthority = ame_util.postApprover) then
1677 return(2);
1678 else
1679 return(1);
1680 end if;
1681 end if;
1682 exception
1683 when others then
1684 ame_util.runtimeException(packageNameIn => 'ame_engine',
1685 routineNameIn => 'getHandlerSublistOrderNum',
1686 exceptionNumberIn => sqlcode,
1687 exceptionStringIn => sqlerrm);
1688 raise;
1689 return(null);
1690 end getHandlerSublistOrderNum;
1691 function getHeaderAttValue1(attributeIdIn in integer) return varchar2 as
1692 begin
1693 return(engAttributeValues1(engAttributeValueIndexes(attributeIdIn)));
1694 exception
1695 when others then
1696 ame_util.runtimeException(packageNameIn => 'ame_engine',
1697 routineNameIn => 'getHeaderAttValue1',
1698 exceptionNumberIn => sqlcode,
1699 exceptionStringIn => sqlerrm);
1700 raise;
1701 return(null);
1702 end getHeaderAttValue1;
1703 function getTestVariantAttValue(attributeIdIn in integer,
1704 itemClassIdIn in integer,
1705 itemIdIn in varchar2) return number as
1706 tempValue ame_util.attributeValueType;
1707 begin
1708 select attribute_value_1 into tempValue from ame_test_trans_att_values
1709 where application_id = engAmeApplicationId
1710 and transaction_id = engTransactionId
1711 and attribute_id = attributeIdIn
1712 and item_class_id = itemClassIdIn
1713 and item_id = itemIdIn;
1714 return tempValue;
1715 exception
1716 when no_data_found then
1717 begin
1718 select attribute_value_1
1719 into tempValue
1720 from ame_test_trans_att_values
1721 where application_id = engAmeApplicationId
1722 and transaction_id = engTransactionId
1723 and attribute_id = attributeIdIn
1724 and item_class_id = getItemClassId(ame_util.headerItemClassName)
1725 and item_id = engTransactionId;
1726 return tempValue;
1727 exception
1728 when others then
1729 ame_util.runtimeException(packageNameIn => 'ame_engine',
1730 routineNameIn => 'getTestVariantAttValue',
1731 exceptionNumberIn => sqlcode,
1732 exceptionStringIn => sqlerrm);
1733 raise;
1734 return(null);
1735 end;
1736 when others then
1737 ame_util.runtimeException(packageNameIn => 'ame_engine',
1738 routineNameIn => 'getTestVariantAttValue',
1739 exceptionNumberIn => sqlcode,
1740 exceptionStringIn => sqlerrm);
1741 raise;
1742 return(null);
1743 end getTestVariantAttValue;
1744 function getHeaderAttValue2(attributeNameIn in varchar2) return varchar2 as
1745 attributeId integer;
1746 begin
1747 if engIsTestTransaction then
1748 attributeId := getAttributeIdByName(attributeNameIn => attributeNameIn);
1749 if checkAttributeVariant(attributeId) = ame_util.booleanTrue then
1750 return getTestVariantAttValue(attributeIdIn => attributeId
1751 ,itemClassIdIn => engAppRuleItemClassIds(engAppHandlerFirstIndex)
1752 ,itemIdIn => engAppAppItemIds(engAppHandlerFirstIndex));
1753 else
1754 return(engAttributeValues1(engAttributeValueIndexes(getAttributeIdByName(attributeNameIn => attributeNameIn))));
1755 end if;
1756 else
1757 if(engAttributeVariant.exists(getAttributeIdByName(attributeNameIn => attributeNameIn))) then
1758 return(getVariantAttributeValue(attributeIdIn => getAttributeIdByName(attributeNameIn => attributeNameIn),
1759 itemClassIn => getItemClassName(itemClassIdIn => engAppRuleItemClassIds(engAppHandlerFirstIndex)),
1760 itemIdIn => engAppAppItemIds(engAppHandlerFirstIndex)));
1761 else
1762 return(engAttributeValues1(engAttributeValueIndexes(getAttributeIdByName(attributeNameIn => attributeNameIn))));
1763 end if;
1764 end if;
1765 exception
1766 when others then
1767 ame_util.runtimeException(packageNameIn => 'ame_engine',
1768 routineNameIn => 'getHeaderAttValue2',
1769 exceptionNumberIn => sqlcode,
1770 exceptionStringIn => sqlerrm);
1771 raise;
1772 return(null);
1773 end getHeaderAttValue2;
1774 function getItemAttValue1(attributeIdIn in integer,
1775 itemIdIn in varchar2) return varchar2 as
1776 begin
1777 return(engAttributeValues1(engAttributeValueIndexes(attributeIdIn) +
1778 getItemOffset(itemClassIdIn => engAttributeItemClassIds(attributeIdIn),
1779 itemIdIn => itemIdIn)));
1780 exception
1781 when others then
1782 ame_util.runtimeException(packageNameIn => 'ame_engine',
1783 routineNameIn => 'getItemAttValue1',
1784 exceptionNumberIn => sqlcode,
1785 exceptionStringIn => sqlerrm);
1786 raise;
1787 return(null);
1788 end getItemAttValue1;
1789 function getItemAttValue2(attributeNameIn in varchar2,
1790 itemIdIn in varchar2) return varchar2 as
1791 attributeId integer;
1792 begin
1793 attributeId := getAttributeIdByName(attributeNameIn => attributeNameIn);
1794 return(engAttributeValues1(engAttributeValueIndexes(attributeId) +
1795 getItemOffset(itemClassIdIn => engAttributeItemClassIds(attributeId),
1796 itemIdIn => itemIdIn)));
1797 exception
1798 when others then
1799 ame_util.runtimeException(packageNameIn => 'ame_engine',
1800 routineNameIn => 'getItemAttValue2',
1801 exceptionNumberIn => sqlcode,
1802 exceptionStringIn => sqlerrm);
1803 raise;
1804 return(null);
1805 end getItemAttValue2;
1806 function getItemClassId(itemClassNameIn in varchar2) return integer as
1807 begin
1808 for itemClassIndex in 1 .. engItemClassNames.count loop
1809 if(engItemClassNames(itemClassIndex) = itemClassNameIn) then
1810 return(engItemClassIds(itemClassIndex));
1811 end if;
1812 end loop;
1813 return(null);
1814 exception
1815 when others then
1816 ame_util.runtimeException(packageNameIn => 'ame_engine',
1817 routineNameIn => 'getItemClassId',
1818 exceptionNumberIn => sqlcode,
1819 exceptionStringIn => sqlerrm);
1820 raise;
1821 return(null);
1822 end getItemClassId;
1823 function getItemClassName(itemClassIdIn in integer) return varchar2 as
1824 begin
1825 return(engItemClassNames(engItemClassIndexes(itemClassIdIn)));
1826 exception
1827 when others then
1828 ame_util.runtimeException(packageNameIn => 'ame_engine',
1829 routineNameIn => 'getItemClassName',
1830 exceptionNumberIn => sqlcode,
1831 exceptionStringIn => sqlerrm);
1832 raise;
1833 return(null);
1834 end getItemClassName;
1835 function getItemClassOrderNumber(itemClassIdIn in integer) return integer as
1836 begin
1837 return(engItemClassOrderNumbers(engItemClassIndexes(itemClassIdIn)));
1838 exception
1839 when others then
1840 ame_util.runtimeException(packageNameIn => 'ame_engine',
1841 routineNameIn => 'getItemClassOrderNumber',
1842 exceptionNumberIn => sqlcode,
1843 exceptionStringIn => sqlerrm);
1844 raise;
1845 return(null);
1846 end getItemClassOrderNumber;
1847 function getItemClassParMode(itemClassIdIn in integer) return varchar2 as
1848 begin
1849 return(engItemClassParModes(engItemClassIndexes(itemClassIdIn)));
1850 exception
1851 when others then
1852 ame_util.runtimeException(packageNameIn => 'ame_engine',
1853 routineNameIn => 'getItemClassParMode',
1854 exceptionNumberIn => sqlcode,
1855 exceptionStringIn => sqlerrm);
1856 raise;
1857 return(null);
1858 end getItemClassParMode;
1859 function getItemClassSublistMode(itemClassIdIn in integer) return varchar2 as
1860 begin
1861 return(engItemClassSublistModes(engItemClassIndexes(itemClassIdIn)));
1862 exception
1863 when others then
1864 ame_util.runtimeException(packageNameIn => 'ame_engine',
1865 routineNameIn => 'getItemClassSublistMode',
1866 exceptionNumberIn => sqlcode,
1867 exceptionStringIn => sqlerrm);
1868 raise;
1869 return(null);
1870 end getItemClassSublistMode;
1871 function getItemIndex(itemClassIdIn in integer,
1872 itemIdIn in varchar2) return integer as
1873 errorCode integer;
1874 errorMessage ame_util.longestStringType;
1875 firstItemIndex integer;
1876 itemClassIndex integer;
1877 noIndexException exception;
1878 begin
1879 itemClassIndex := engItemClassIndexes(itemClassIdIn);
1880 firstItemIndex := engItemClassItemIdIndexes(itemClassIndex);
1881 for i in firstItemIndex .. (firstItemIndex + engItemCounts(itemClassIndex) - 1) loop
1882 if(engItemIds(i) = itemIdIn) then
1883 return(i);
1884 end if;
1885 end loop;
1886 raise noIndexException;
1887 exception
1888 when noIndexException then
1889 errorCode := -20001;
1890 errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
1891 messageNameIn => 'AME_400682_ENG_INV_ITEM_OFFSET');
1892 ame_util.runtimeException(packageNameIn => 'ame_engine',
1893 routineNameIn => 'getItemIndex',
1894 exceptionNumberIn => errorCode,
1895 exceptionStringIn => errorMessage);
1896 raise_application_error(errorCode,
1897 errorMessage);
1898 return(null);
1899 when others then
1900 ame_util.runtimeException(packageNameIn => 'ame_engine',
1901 routineNameIn => 'getItemIndex',
1902 exceptionNumberIn => sqlcode,
1903 exceptionStringIn => sqlerrm);
1904 raise;
1905 return(null);
1906 end getItemIndex;
1907 function getItemOffset(itemClassIdIn in integer,
1908 itemIdIn in varchar2) return integer as
1909 errorCode integer;
1910 errorMessage ame_util.longestStringType;
1911 firstItemIndex integer;
1912 itemClassIndex integer;
1913 noOffsetException exception;
1914 begin
1915 itemClassIndex := engItemClassIndexes(itemClassIdIn);
1916 firstItemIndex := engItemClassItemIdIndexes(itemClassIndex);
1917 for i in firstItemIndex .. (firstItemIndex + engItemCounts(itemClassIndex) - 1) loop
1918 if(engItemIds(i) = itemIdIn) then
1919 return(i - firstItemIndex);
1920 end if;
1921 end loop;
1922 raise noOffsetException;
1923 exception
1924 when noOffsetException then
1925 errorCode := -20001;
1926 errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
1927 messageNameIn => 'AME_400682_ENG_INV_ITEM_OFFSET');
1928 ame_util.runtimeException(packageNameIn => 'ame_engine',
1929 routineNameIn => 'getItemOffset',
1930 exceptionNumberIn => errorCode,
1931 exceptionStringIn => errorMessage);
1932 raise_application_error(errorCode,
1933 errorMessage);
1934 return(null);
1935 when others then
1936 ame_util.runtimeException(packageNameIn => 'ame_engine',
1937 routineNameIn => 'getItemOffset',
1938 exceptionNumberIn => sqlcode,
1939 exceptionStringIn => sqlerrm);
1940 raise;
1941 return(null);
1942 end getItemOffset;
1943 function getItemOrderNumber(itemClassNameIn in varchar2,
1944 itemIdIn in varchar2) return integer as
1945 itemClassId integer;
1946 begin
1947 itemClassId := getItemClassId(itemClassNameIn => itemClassNameIn);
1948 if(getItemClassParMode(itemClassIdIn => itemClassId) = ame_util.parallelItems) then
1949 return(1);
1950 else /* The parallelization modes is ame_util.serialItems. */
1951 return(1 + getItemOffset(itemClassIdIn => itemClassId,
1952 itemIdIn => itemIdIn));
1953 end if;
1954 exception
1955 when others then
1956 ame_util.runtimeException(packageNameIn => 'ame_engine',
1957 routineNameIn => 'getItemOrderNumber',
1958 exceptionNumberIn => sqlcode,
1959 exceptionStringIn => sqlerrm);
1960 raise;
1961 return(null);
1962 end getItemOrderNumber;
1963 function getNextInsertionOrder return integer as
1964 maxInsertionOrderNumber number;
1965 begin
1966 select max(insertion_order)
1967 into maxInsertionOrderNumber
1968 from ame_temp_insertions
1969 where transaction_id = engTransactionId
1970 and application_id = engAmeApplicationId;
1971 if maxinsertionOrderNumber is null
1972 then
1973 return 1;
1974 else
1975 return (maxInsertionOrderNumber + 1);
1976 end if;
1977 exception
1978 when others then
1979 ame_util.runtimeException(packageNameIn => 'ame_engine',
1980 routineNameIn => 'getNextInsertionOrder',
1981 exceptionNumberIn => sqlcode,
1982 exceptionStringIn => sqlerrm);
1983 raise;
1984 return(null);
1985 end getNextInsertionOrder;
1986 function getNullActionTypeOrderNumber return integer as
1987 maxOrderNumber integer := 0;
1988 tempIndex integer;
1989 begin
1990 tempIndex := engActionTypeOrderNumbers.first;
1991 while(tempIndex is not null) loop
1992 if(maxOrderNumber is null or
1993 engActionTypeOrderNumbers(tempIndex) < maxOrderNumber) then
1994 maxOrderNumber := engActionTypeOrderNumbers(tempIndex);
1995 end if;
1996 tempIndex := engActionTypeOrderNumbers.next(tempIndex);
1997 end loop;
1998 return(maxOrderNumber + 1);
1999 exception
2000 when others then
2001 ame_util.runtimeException(packageNameIn => 'ame_engine',
2002 routineNameIn => 'getNullActionTypeOrderNumber',
2003 exceptionNumberIn => sqlcode,
2004 exceptionStringIn => sqlerrm);
2005 raise;
2006 return(null);
2007 end getNullActionTypeOrderNumber;
2008 function getRuntimeGroupCount(groupIdIn in integer) return integer as
2009 tempIndex integer;
2010 begin
2011 tempIndex := 0; /* pre-increment */
2012 -- Check if group is defined or has to be re run for every item class/item ID
2013 if(not engGroupUseItemBind.exists(groupIdIn)) then
2014 fetchRuntimeGroup(groupIdIn => groupIdIn);
2015 elsif (engGroupUseItemBind(groupIdIn) = ame_util.booleanTrue) then
2016 fetchRuntimeGroup(groupIdIn => groupIdIn);
2017 end if;
2018 /* Group membership must exist in engGroupMemberGroupIds now. */
2019 for i in 1 .. engGroupMemberGroupIds.count loop
2020 if(engGroupMemberGroupIds(i) = groupIdIn) then
2021 tempIndex := tempIndex + 1;
2022 elsif(tempIndex > 0) then
2023 /* The group was found and has been passed. */
2024 return(tempIndex);
2025 end if;
2026 end loop;
2027 exception
2028 when others then
2029 ame_util.runtimeException(packageNameIn => 'ame_engine',
2030 routineNameIn => 'getRuntimeGroupCount',
2031 exceptionNumberIn => sqlcode,
2032 exceptionStringIn => sqlerrm);
2033 raise;
2034 return(null);
2035 end getRuntimeGroupCount;
2036 function getSublistOrderNum(itemClassNameIn in varchar2,
2037 authorityIn in varchar2) return integer as
2038 itemClassSublistMode ame_util.charType;
2039 begin
2040 itemClassSublistMode :=
2041 getItemClassSublistMode(itemClassIdIn => getItemClassId(itemClassNameIn => itemClassNameIn));
2042 if(itemClassSublistMode = ame_util.serialSublists) then
2043 if(authorityIn = ame_util.preApprover) then
2044 return(1);
2045 elsif(authorityIn = ame_util.authorityApprover) then
2046 return(2);
2047 else
2048 return(3);
2049 end if;
2050 elsif(itemClassSublistMode = ame_util.parallelSublists) then
2051 return(1);
2052 elsif(itemClassSublistMode = ame_util.preFirst) then
2053 if(authorityIn = ame_util.preApprover) then
2054 return(1);
2055 else
2056 return(2);
2057 end if;
2058 else
2059 if(authorityIn = ame_util.postApprover) then
2060 return(2);
2061 else
2062 return(1);
2063 end if;
2064 end if;
2065 exception
2066 when others then
2067 ame_util.runtimeException(packageNameIn => 'ame_engine',
2068 routineNameIn => 'getSublistOrderNum',
2069 exceptionNumberIn => sqlcode,
2070 exceptionStringIn => sqlerrm);
2071 raise;
2072 return(null);
2073 end getSublistOrderNum;
2074 function getTransactionId return varchar2 as
2075 begin
2076 return(engTransactionID);
2077 exception
2078 when others then
2079 ame_util.runtimeException(packageNameIn => 'ame_engine',
2080 routineNameIn => 'getTransactionId',
2081 exceptionNumberIn => sqlcode,
2082 exceptionStringIn => sqlerrm);
2083 raise;
2084 return(null);
2085 end getTransactionId;
2086 function getTransactionTypeId return varchar2 as
2087 begin
2088 return(engTransactionTypeID);
2089 exception
2090 when others then
2091 ame_util.runtimeException(packageNameIn => 'ame_engine',
2092 routineNameIn => 'getTransactionTypeId',
2093 exceptionNumberIn => sqlcode,
2094 exceptionStringIn => sqlerrm);
2095 raise;
2096 return(null);
2097 end getTransactionTypeId;
2098 /********************************** sort functions **********************************/
2099 function compareApplicableRules(index1In in integer,
2100 index2In in integer,
2101 compareActionTypesIn in boolean) return boolean as
2102 /* Returns true if the applicable rule at the first index weakly precedes the second. */
2103 actionTypeId1 integer;
2104 actionTypeId2 integer;
2105 itemClassId1 integer;
2106 itemClassId2 integer;
2107 begin
2108 itemClassId1 := engAppRuleItemClassIds(index1In);
2109 itemClassId2 := engAppRuleItemClassIds(index2In);
2110 /* Account for the possibility that one or both rules may have null item-class IDs. */
2111 if(itemClassId1 is null) then
2112 if(itemClassId2 is not null) then
2113 return(false);
2114 end if;
2115 else /* itemClassId1 is not null. */
2116 if(itemClassId2 is null) then
2117 return(true);
2118 else /* Both item-class IDs are non-null. */
2119 /* item-class order number */
2120 if(engItemClassOrderNumbers(engItemClassIndexes(itemClassId1)) >
2121 engItemClassOrderNumbers(engItemClassIndexes(itemClassId2))) then
2122 return(false);
2123 end if;
2124 if(engItemClassOrderNumbers(engItemClassIndexes(itemClassId1)) <
2125 engItemClassOrderNumbers(engItemClassIndexes(itemClassId2))) then
2126 return(true);
2127 end if;
2128 /* item-class ID */
2129 if(itemClassId1 > itemClassId2) then
2130 return(false);
2131 end if;
2132 if(itemClassId1 < itemClassId2) then
2133 return(true);
2134 end if;
2135 end if;
2136 end if;
2137 /* item ID */
2138 if(engAppAppItemIds(index1In) > engAppAppItemIds(index2In)) then
2139 return(false);
2140 end if;
2141 if(engAppAppItemIds(index1In) < engAppAppItemIds(index2In)) then
2142 return(true);
2143 end if;
2144 /* rule type */
2145 if(engAppRuleTypes(index1In) > engAppRuleTypes(index2In)) then
2146 return(false);
2147 end if;
2148 /*
2149 The second rule-type comparison is only necessary if compareActionTypesIn is true;
2150 otherwise, we return true regardless of the outcome of the second rule-type comparison.
2151 So include it within the if(compareActionTypesIn) below.
2152 /* optional action-type comparisons */
2153 if(compareActionTypesIn) then
2154 if(engAppRuleTypes(index1In) < engAppRuleTypes(index2In)) then
2155 return(true);
2156 end if;
2157 /* Do the action-type comparisons. */
2158 actionTypeId1 := engAppActionTypeIds(index1In);
2159 actionTypeId2 := engAppActionTypeIds(index2In);
2160 /* action-type order numbers */
2161 if(engActionTypeOrderNumbers(actionTypeId1) >
2162 engActionTypeOrderNumbers(actionTypeId2)) then
2163 return(false);
2164 end if;
2165 if(engActionTypeOrderNumbers(actionTypeId1) <
2166 engActionTypeOrderNumbers(actionTypeId2)) then
2167 return(true);
2168 end if;
2169 /* action-type ID */
2170 if(actionTypeId1 > actionTypeId2) then
2171 return(false);
2172 end if;
2173 /*
2174 The second comparison on action-type ID is unnecessary, because whether it succeeds
2175 or fails, we return true.
2176 */
2177 end if;
2178 return(true);
2179 exception
2180 when others then
2181 ame_util.runtimeException(packageNameIn => 'ame_engine',
2182 routineNameIn => 'compareApplicableRules',
2183 exceptionNumberIn => sqlcode,
2184 exceptionStringIn => sqlerrm);
2185 raise;
2186 return(false);
2187 end compareApplicableRules;
2188 /*************************************************************************************
2189 procedures
2190 *************************************************************************************/
2191 procedure addApprover(approverIn in ame_util.approverRecord2) as
2192 errorCode integer;
2193 errorMessage ame_util.longestStringType;
2194 listTooLongException exception;
2195 nullFieldException exception;
2196 begin
2197 if(engStApprovers.count > 2500) then
2198 raise listTooLongException;
2199 end if;
2200 checkApprover(approverIn => approverIn);
2201 if(approverIn.name is null or
2202 approverIn.orig_system is null or
2203 approverIn.orig_system_id is null or
2204 approverIn.display_name is null or
2205 approverIn.approver_category is null or
2206 approverIn.api_insertion is null or
2207 approverIn.authority is null or
2208 approverIn.action_type_id is null or
2209 approverIn.group_or_chain_id is null or
2210 approverIn.occurrence is null or
2211 approverIn.source is null or
2212 approverIn.item_class is null or
2213 approverIn.item_id is null or
2214 approverIn.item_class_order_number is null or
2215 approverIn.item_order_number is null or
2216 approverIn.sub_list_order_number is null or
2217 approverIn.action_type_order_number is null or
2218 approverIn.group_or_chain_order_number is null or
2219 approverIn.member_order_number is null) then
2220 raise nullFieldException;
2221 end if;
2222 ame_util.copyApproverRecord2(approverRecord2In => approverIn,
2223 approverRecord2Out => engStApprovers(engStApprovers.count + 1));
2224 /* Add the approver to the tree whenever he is added to the approver list */
2225 /* Approvers location in list is engStApprovers.count */
2226 /* Add the approver as the last approver among the approvers with same */
2227 /* order number */
2228 if engPrepareApproverTree then
2229 addApproverToTree
2230 (approverRecordIn => engStApprovers(engStApprovers.count)
2231 ,approverIndexIn => engStApprovers.count
2232 ,approverLocationIn => ame_util.lastAmongEquals);
2233 end if;
2234 exception
2235 when listTooLongException then
2236 errorCode := -20001;
2237 errorMessage :=
2238 ame_util.getMessage(applicationShortNameIn => 'PER',
2239 messageNameIn => 'AME_400118_ENG_LOOP_CHA_AUTH');
2240 ame_util.runtimeException(packageNameIn => 'ame_engine',
2241 routineNameIn => 'addApprover',
2242 exceptionNumberIn => errorCode,
2243 exceptionStringIn => errorMessage);
2244 raise_application_error(errorCode,
2245 errorMessage);
2246 when nullFieldException then
2247 errorCode := -20001;
2248 errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
2249 messageNameIn => 'AME_400683_APPR_REC_INV');
2250 ame_util.runtimeException(packageNameIn => 'ame_engine',
2251 routineNameIn => 'addApprover',
2252 exceptionNumberIn => errorCode,
2253 exceptionStringIn => errorMessage);
2254 raise_application_error(errorCode,
2255 errorMessage);
2256 when others then
2257 ame_util.runtimeException(packageNameIn => 'ame_engine',
2258 routineNameIn => 'addApprover',
2259 exceptionNumberIn => sqlcode,
2260 exceptionStringIn => sqlerrm);
2261 raise;
2262 end addApprover;
2263 procedure addApproversTodevList(approverRecordIndexIn in integer) is
2264 tempCount integer;
2265 begin
2266 if engTempReason is not null or engTempDate is not null then
2267 engDeviationResultList(approverRecordIndexIn).reason := engTempReason;
2268 engDeviationResultList(approverRecordIndexIn).effectiveDate := engTempDate;
2269 end if;
2270 engTempReason := null;
2271 engTempDate := null;
2272 exception
2273 when others then
2274 ame_util.runtimeException(packageNameIn => 'ame_engine',
2275 routineNameIn => 'addApproversTodevList',
2276 exceptionNumberIn => sqlcode,
2277 exceptionStringIn => sqlerrm);
2278 end addApproversTodevList;
2279 /* This procedure is used to add an approver to the approver tree */
2280 procedure addApproverToTree
2281 (approverRecordIn in ame_util.approverRecord2
2282 ,approverIndexIn in integer
2283 ,approverLocationIn in boolean default ame_util.lastAmongEquals) is
2284 orderNumbers ame_util.idList;
2285 treeLevelIds ame_util.stringList;
2286 approverIndexs ame_util.idList;
2287 previousTreeNodeIndex integer;
2288 currentTreeNodeIndex integer;
2289 newTreeNodeIndex integer;
2290 newTreeNode ame_util.approverTreeRecord;
2291 currentSiblingTreeNodeIndex integer;
2292 lowerOrderLastSiblingIndex integer;
2293 higherOrderFirstSiblingIndex integer;
2294 sameOrderFirstSiblingIndex integer;
2295 sameOrderLastSiblingIndex integer;
2296 currentTreeNodeFound boolean;
2297 begin
2298 /* Initialise the tree with the transaction level node if the tree */
2299 /* is not yet built.The tree level node will have min_order of 1 */
2300 /* which is the minimum allowed approver order number */
2301 if engStApproversTree.count = 0 then
2302 newTreeNode.parent_index := ame_util.noParentIndex;
2303 newTreeNode.child_index := ame_util.noChildIndex;
2304 newTreeNode.sibling_index := ame_util.noSiblingIndex;
2305 newTreeNode.approver_index := ame_util.noApproverIndex;
2306 newTreeNode.tree_level_id := -1;
2307 newTreeNode.order_number := -1;
2308 newTreeNode.min_order := ame_util.minimumApproverOrderNumber;
2309 newTreeNode.is_suspended := ame_util.booleanFalse;
2310 -- newTreeNode.repeated_index := -1;
2311 newTreeNode.tree_level := 0;
2312 engStApproversTree(1) := newTreeNode;
2313 end if;
2314 /* For each tree level assign the node order number, unique tree level */
2315 /* ids and the approver indices */
2316 orderNumbers(1) := approverRecordIn.item_class_order_number;
2317 orderNumbers(2) := approverRecordIn.item_order_number;
2318 orderNumbers(3) := approverRecordIn.sub_list_order_number;
2319 orderNumbers(4) := approverRecordIn.action_type_order_number;
2320 orderNumbers(5) := approverRecordIn.group_or_chain_order_number;
2321 orderNumbers(6) := approverRecordIn.member_order_number;
2322 treeLevelIds(1) := approverRecordIn.item_class;
2323 treeLevelIds(2) := approverRecordIn.item_id;
2324 treeLevelIds(3) := approverRecordIn.authority;
2325 treeLevelIds(4) := to_char(approverRecordIn.action_type_id);
2326 treeLevelIds(5) := to_char(approverRecordIn.group_or_chain_id);
2327 treeLevelIds(6) := approverRecordIn.name;
2328 approverIndexs(1) := ame_util.noApproverIndex;
2329 approverIndexs(2) := ame_util.noApproverIndex;
2330 approverIndexs(3) := ame_util.noApproverIndex;
2331 approverIndexs(4) := ame_util.noApproverIndex;
2332 approverIndexs(5) := ame_util.noApproverIndex;
2333 approverIndexs(6) := approverIndexIn;
2334 /* Starting with the transaction node traverse the tree through the */
2335 /* item class,item,sublist,action type,group or chain and finally */
2336 /* insert the approver into the tree.In the way if any of other nodes */
2337 /* are missing create them. */
2338 previousTreeNodeIndex := 1;
2339 for i in 1 .. 6 loop
2340 if engStApproversTree(previousTreeNodeIndex).child_index
2341 = ame_util.noChildIndex then
2342 newTreeNode.parent_index := previousTreeNodeIndex;
2343 newTreeNode.sibling_index := ame_util.noSiblingIndex;
2344 newTreeNode.child_index := ame_util.noChildIndex;
2345 newTreeNode.approver_index := approverIndexs(i);
2346 newTreeNode.tree_level_id := treeLevelIds(i);
2347 newTreeNode.order_number := orderNumbers(i);
2348 newTreeNode.is_suspended := ame_util.booleanFalse;
2349 newTreeNode.tree_level := i;
2350 newTreeNodeIndex := engStApproversTree.last + 1;
2351 engStApproversTree(newTreeNodeIndex) := newTreeNode;
2352 engStApproversTree(previousTreeNodeIndex).child_index := newTreeNodeIndex;
2353 currentTreeNodeIndex := newTreeNodeIndex;
2354 else
2355 currentSiblingTreeNodeIndex :=
2356 engStApproversTree(previousTreeNodeIndex).child_index;
2357 lowerOrderLastSiblingIndex := -1;
2358 higherOrderFirstSiblingIndex := -1;
2359 sameOrderFirstSiblingIndex := -1;
2360 sameOrderLastSiblingIndex := -1;
2361 currentTreeNodeFound := false;
2362 loop
2363 if engStApproversTree(currentSiblingTreeNodeIndex).order_number
2364 < orderNumbers(i) then
2365 lowerOrderLastSiblingIndex := currentSiblingTreeNodeIndex;
2366 elsif engStApproversTree(currentSiblingTreeNodeIndex).order_number
2367 = orderNumbers(i) then
2368 if engStApproversTree(currentSiblingTreeNodeIndex).tree_level_id
2369 = treeLevelIds(i)
2370 and (i <> 6) then --added for bug 4232137
2371 currentTreeNodeIndex := currentSiblingTreeNodeIndex;
2372 currentTreeNodeFound := true;
2373 exit;
2374 end if;
2375 if sameOrderFirstSiblingIndex = -1 then
2376 sameOrderFirstSiblingIndex := currentSiblingTreeNodeIndex;
2377 end if;
2378 sameOrderLastSiblingIndex := currentSiblingTreeNodeIndex;
2379 elsif engStApproversTree(currentSiblingTreeNodeIndex).order_number
2380 > orderNumbers(i) then
2381 if higherOrderFirstSiblingIndex = -1 then
2382 higherOrderFirstSiblingIndex := currentSiblingTreeNodeIndex;
2383 end if;
2384 end if;
2385 currentSiblingTreeNodeIndex
2386 := engStApproversTree(currentSiblingTreeNodeIndex).sibling_index;
2387 exit when currentSiblingTreeNodeIndex = ame_util.noSiblingIndex;
2388 end loop;
2389 if not currentTreeNodeFound then
2390 if approverLocationIn then
2391 /* approverLocationIn is ame_util.firstAmongEquals */
2392 newTreeNode.parent_index := previousTreeNodeIndex;
2393 if sameOrderFirstSiblingIndex = -1 then
2394 newTreeNode.sibling_index := higherOrderFirstSiblingIndex;
2395 else
2396 newTreeNode.sibling_index := sameOrderFirstSiblingIndex;
2397 end if;
2398 newTreeNode.child_index := ame_util.noChildIndex;
2399 newTreeNode.approver_index := approverIndexs(i);
2400 newTreeNode.tree_level_id := treeLevelIds(i);
2401 newTreeNode.order_number := orderNumbers(i);
2402 newTreeNode.is_suspended := ame_util.booleanFalse;
2403 newTreeNode.tree_level := i;
2404 newTreeNodeIndex := engStApproversTree.last + 1;
2405 engStApproversTree(newTreeNodeIndex) := newTreeNode;
2406 if lowerOrderLastSiblingIndex = -1 then
2407 engStApproversTree(previousTreeNodeIndex).child_index := newTreeNodeIndex;
2408 else
2409 engStApproversTree(lowerOrderLastSiblingIndex).sibling_index := newTreeNodeIndex;
2410 end if;
2411 currentTreeNodeIndex := newTreeNodeIndex;
2412 else
2413 /* approverLocationIn is ame_util.lastAmongEquals */
2414 newTreeNode.parent_index := previousTreeNodeIndex;
2415 newTreeNode.sibling_index := higherOrderFirstSiblingIndex;
2416 newTreeNode.child_index := ame_util.noChildIndex;
2417 newTreeNode.approver_index := approverIndexs(i);
2418 newTreeNode.tree_level_id := treeLevelIds(i);
2419 newTreeNode.order_number := orderNumbers(i);
2420 newTreeNode.is_suspended := ame_util.booleanFalse;
2421 newTreeNode.tree_level := i;
2422 newTreeNodeIndex := engStApproversTree.last + 1;
2423 engStApproversTree(newTreeNodeIndex) := newTreeNode;
2424 if sameOrderLastSiblingIndex = -1 and lowerOrderLastSiblingIndex = -1 then
2425 engStApproversTree(previousTreeNodeIndex).child_index := newTreeNodeIndex;
2426 elsif sameOrderLastSiblingIndex = -1 then
2427 engStApproversTree(lowerOrderLastSiblingIndex).sibling_index := newTreeNodeIndex;
2428 else
2429 engStApproversTree(sameOrderLastSiblingIndex).sibling_index := newTreeNodeIndex;
2430 end if;
2431 currentTreeNodeIndex := newTreeNodeIndex;
2432 end if;
2433 end if;
2434 end if;
2435 previousTreeNodeIndex := currentTreeNodeIndex;
2436 end loop;
2437 addApproversTodevList(approverRecordIndexIn => approverIndexIn);
2438 exception
2439 when others then
2440 ame_util.runtimeException(packageNameIn => 'ame_engine',
2441 routineNameIn => 'addApproverToTree',
2442 exceptionNumberIn => sqlcode,
2443 exceptionStringIn => sqlerrm);
2444 raise;
2445 end addApproverToTree;
2446 procedure calculateApproverOrderNumbers as
2447 maximumApproverOrderNumber integer;
2448 transactionApprovalStatus integer;
2449 transactionhasSuspendedItems boolean;
2450 stoppingRule ame_util.stringType;
2451 headerItemRejected boolean;
2452 loopIndex integer;
2453 begin
2454 /* The call to finalizeTree does the following */
2455 /* 1.Calculate the approver order number */
2456 /* 2.Populates the list of rejected items and itemclasses */
2457 /* 3.Returns whether the transaction has rejected Items */
2458 /* 4.Returns the maximum order number of approvers */
2459 /* 5.Returns the approval status of the transaction */
2460 finalizeTree
2461 (parentIndexIn => 1
2462 ,maximumOrderOut => maximumApproverOrderNumber
2463 ,approvalStatusOut => transactionApprovalStatus
2464 ,rejectedItemsExistOut => transactionhasSuspendedItems);
2465 engStApproversTree(1).status := transactionApprovalStatus;
2466 engStApproversTree(1).max_order := maximumApproverOrderNumber;
2467 stoppingRule := ame_engine.getHeaderAttValue2
2468 (attributeNameIn => ame_util.rejectionResponseAttribute);
2469 if transactionhasSuspendedItems then
2470 /* Check if any of the suspended item is a header item */
2471 /* If a header item is suspended then it is as good as */
2472 /* the entire transaction being suspended */
2473 headerItemRejected := false;
2474 for i in 1 .. engStSuspendedItemClasses.count loop
2475 if engStSuspendedItemClasses(i) = ame_util.headerItemClassName then
2476 headerItemRejected := true;
2477 exit;
2478 end if;
2479 end loop;
2480 if stoppingRule = ame_util.stopAllItems or headerItemRejected then
2481 /* Suspend the transaction node */
2482 engStApproversTree(1).is_suspended := ame_util.booleanTrue;
2483 elsif stoppingRule = ame_util.continueAllOtherItems then
2484 /* Suspend all items in the suspended items list */
2485 for i in 1 .. engStSuspendedItems.count loop
2486 /* Approvers Tree can be sparse */
2487 loopIndex := engStApproversTree.first;
2488 loop
2489 if(engStApproversTree(loopIndex).tree_level = 2 and
2490 engStApproversTree(loopIndex).tree_level_id = engStSuspendedItems(i) and
2491 engStApproversTree(engStApproversTree(loopIndex).parent_index).tree_level_id
2492 = engStSuspendedItemClasses(i)) then
2493 engStApproversTree(loopIndex).is_suspended := ame_util.booleanTrue;
2494 exit;
2495 end if;
2496 exit when loopIndex = engStApproversTree.last;
2497 loopIndex := engStApproversTree.next(loopIndex);
2498 end loop;
2499 end loop;
2500 elsif stoppingRule = ame_util.continueOtherSubItems then
2501 /* Suspend all items in the suspended items list and header item */
2502 for i in 1 .. engStSuspendedItems.count loop
2503 /* Approvers Tree can be sparse */
2504 loopIndex := engStApproversTree.first;
2505 loop
2506 if(engStApproversTree(loopIndex).tree_level = 2 and
2507 ((engStApproversTree(loopIndex).tree_level_id = engStSuspendedItems(i) and
2508 engStApproversTree(engStApproversTree(loopIndex).parent_index).tree_level_id
2509 = engStSuspendedItemClasses(i))
2510 or
2511 (engStApproversTree(engStApproversTree(loopIndex).parent_index).tree_level_id
2512 = ame_util.headerItemClassName))) then
2513 engStApproversTree(loopIndex).is_suspended := ame_util.booleanTrue;
2514 end if;
2515 exit when loopIndex = engStApproversTree.last;
2516 loopIndex := engStApproversTree.next(loopIndex);
2517 end loop;
2518 end loop;
2519 end if;
2520 end if;
2521 exception
2522 when others then
2523 ame_util.runtimeException(packageNameIn => 'ame_engine',
2524 routineNameIn => 'calculateApproverOrderNumbers',
2525 exceptionNumberIn => sqlcode,
2526 exceptionStringIn => sqlerrm);
2527 raise;
2528 end calculateApproverOrderNumbers;
2529 --+
2530 --+ check Approver
2531 --+
2532 procedure checkApprover(approverIn in ame_util.approverRecord2) is
2533 errorCode integer;
2534 errorMessage ame_util.longestStringType;
2535 tempApproverTypeCount integer;
2536 tempApproverType ame_approver_types.orig_system%type;
2537 invalidApproverException1 exception;
2538 invalidApproverException2 exception;
2539 begin
2540 tempApproverType := approverIn.orig_system;
2541 if tempApproverType like 'FND_RESP%' or tempApproverType = 'AME_INS_ORIG_SYSTEM' then
2542 return;
2543 end if;
2544 if getConfigVarValue(ame_util.allowAllApproverTypesConfigVar) = ame_util.yes then
2545 select count(*)
2546 into tempApproverTypeCount
2547 from ame_approver_types
2548 where orig_system = approverIn.orig_system
2549 and sysdate between start_date and end_date;
2550 if tempApproverTypeCount = 0 then
2551 raise invalidApproverException1;
2552 end if;
2553 else
2554 if(tempApproverType in (ame_util.perOrigSystem
2555 ,ame_util.fndUserOrigSystem )) then
2556 null;
2557 else
2558 raise invalidApproverException2;
2559 end if;
2560 end if;
2561 exception
2562 when invalidApproverException1 then
2563 errorCode := -20001;
2564 errorMessage := 'The Approver '
2565 ||approverIn.display_name
2566 ||' belongs to approver type '
2567 ||approverIn.orig_system
2568 ||' which is not registered in AME.';
2569 ame_util.runtimeException(packageNameIn => 'ame_engine',
2570 routineNameIn => 'checkApprover',
2571 exceptionNumberIn => errorCode,
2572 exceptionStringIn => errorMessage);
2573 raise_application_error(errorCode,
2574 errorMessage);
2575 when invalidApproverException2 then
2576 errorCode := -20001;
2577 errorMessage := 'The Approver '
2578 ||approverIn.display_name
2579 ||' belongs to approver type '
2580 ||approverIn.orig_system
2581 ||'. And the allowAllApproverTypes configuration variable set to No.';
2582 ame_util.runtimeException(packageNameIn => 'ame_engine',
2583 routineNameIn => 'checkApprover',
2584 exceptionNumberIn => errorCode,
2585 exceptionStringIn => errorMessage);
2586 raise_application_error(errorCode,
2587 errorMessage);
2588 end checkApprover;
2589 --+
2590 procedure clearHandlerState(handlerNameIn in varchar2,
2591 parameterIn in varchar2 default null) as
2592 handlerName ame_temp_handler_states.handler_name%type;
2593 begin
2594 handlerName := upper(handlerNameIn);
2595 delete
2596 from ame_temp_handler_states
2597 where
2598 handler_name = handlerName and
2599 application_id = engAmeApplicationId and
2600 ((parameter is null and parameterIn is null) or
2601 (parameter = parameterIn));
2602 exception
2603 when others then
2604 ame_util.runtimeException(packageNameIn => 'ame_engine',
2605 routineNameIn => 'clearHandlerState',
2606 exceptionNumberIn => sqlcode,
2607 exceptionStringIn => sqlerrm);
2608 raise;
2609 end clearHandlerState;
2610 procedure compactEngAppLists(compactPrioritiesIn in boolean,
2611 compactActionTypeIdsIn in boolean,
2612 compactParametersIn in boolean) as
2613 tempCount integer;
2614 tempFirstIndex integer;
2615 tempLastIndex integer;
2616 begin
2617 tempCount := engAppRuleIds.count;
2618 if(tempCount = 0) then
2619 return;
2620 end if;
2621 tempFirstIndex := engAppRuleIds.first;
2622 for i in 1 .. tempCount loop
2623 if(i <> tempFirstIndex) then /* (Don't copy a row onto itself.) */
2624 engAppItemClassIds(i) := engAppItemClassIds(tempFirstIndex);
2625 engAppItemIds(i) := engAppItemIds(tempFirstIndex);
2626 engAppApproverCategories(i) := engAppApproverCategories(tempFirstIndex);
2627 engAppRuleIds(i) := engAppRuleIds(tempFirstIndex);
2628 engRuleAppliedYN(i) := engRuleAppliedYN(tempFirstIndex);
2629 engAppRuleTypes(i) := engAppRuleTypes(tempFirstIndex);
2630 engAppRuleItemClassIds(i) := engAppRuleItemClassIds(tempFirstIndex);
2631 engAppAppItemIds(i) := engAppAppItemIds(tempFirstIndex);
2632 if(compactPrioritiesIn) then
2633 engAppPriorities(i) := engAppPriorities(tempFirstIndex);
2634 end if;
2635 if(compactActionTypeIdsIn) then
2636 engAppActionTypeIds(i) := engAppActionTypeIds(tempFirstIndex);
2637 end if;
2638 if(compactParametersIn) then
2639 engAppParameters(i) := engAppParameters(tempFirstIndex);
2640 engAppParameterTwos(i) := engAppParameterTwos(tempFirstIndex);
2641 end if;
2642 end if;
2643 tempFirstIndex := engAppRuleIds.next(tempFirstIndex);
2644 end loop;
2645 /*
2646 engAppRuleIds.next will set tempFirstIndex null just before the for loop
2647 exits, so we have to set it anew here.
2648 */
2649 tempFirstIndex := tempCount + 1;
2650 tempLastIndex := engAppRuleIds.last;
2651 engAppItemClassIds.delete(tempFirstIndex, tempLastIndex);
2652 engAppItemIds.delete(tempFirstIndex, tempLastIndex);
2653 engAppApproverCategories.delete(tempFirstIndex, tempLastIndex);
2654 engAppRuleIds.delete(tempFirstIndex, tempLastIndex);
2655 engRuleAppliedYN.delete(tempFirstIndex, tempLastIndex);
2656 engAppRuleTypes.delete(tempFirstIndex, tempLastIndex);
2657 engAppRuleItemClassIds.delete(tempFirstIndex, tempLastIndex);
2658 engAppAppItemIds.delete(tempFirstIndex, tempLastIndex);
2659 if(compactPrioritiesIn) then
2660 engAppPriorities.delete(tempFirstIndex, tempLastIndex);
2661 end if;
2662 if(compactActionTypeIdsIn) then
2663 engAppActionTypeIds.delete(tempFirstIndex, tempLastIndex);
2664 end if;
2665 if(compactParametersIn) then
2666 engAppParameters.delete(tempFirstIndex, tempLastIndex);
2667 engAppParameterTwos.delete(tempFirstIndex, tempLastIndex);
2668 end if;
2669 exception
2670 when others then
2671 ame_util.runtimeException(packageNameIn => 'ame_engine',
2672 routineNameIn => 'compactEngAppLists',
2673 exceptionNumberIn => sqlcode,
2674 exceptionStringIn => sqlerrm);
2675 raise;
2676 end compactEngAppLists;
2677 procedure doPerItemRuleEvaluation(itemClassIdIn in integer,
2678 itemIndexIn in varchar2) as
2679 currentACUsageConditionIds ame_util.idList;
2680 currentACUsageRuleIds ame_util.idList;
2681 currentConditionRuleCounts ame_util.idList;
2682 tempConditionId integer;
2683 tempConditionId2 integer;
2684 tempHighestRuleCount integer;
2685 tempIndex integer;
2686 tempIndex2 integer;
2687 tempIndex3 integer;
2688 tempPendingRuleIds ame_util.idList;
2689 tempRuleApplies boolean;
2690 tempRuleId integer;
2691 begin
2692 /* Handle the null case (no active conditions) first. */
2693 if(not engACUsageFirstIndexes.exists(itemClassIdIn)) then
2694 return;
2695 end if;
2696 /*
2697 Initialize the current condition usages. Note that while the currentACUsage local
2698 variables start out as compact lists, the algorithm that iterates through them
2699 deletes them in an unpredictable order, and does not re-compact the lists; so the
2700 algorithm must treat these lists as sparse.
2701 */
2702 tempIndex := 0; /* pre-increment */
2703 if(engACUsageFirstIndexes.exists(itemClassIdIn)) then
2704 for ACUIndex in
2705 engACUsageFirstIndexes(itemClassIdIn) ..
2706 (engACUsageFirstIndexes(itemClassIdIn) + engACUsageItemClassCounts(itemClassIdIn) - 1) loop
2707 tempIndex := tempIndex + 1;
2708 currentACUsageConditionIds(tempIndex) := engACUsageConditionIds(ACUIndex);
2709 currentACUsageRuleIds(tempIndex) := engACUsageRuleIds(ACUIndex);
2710 end loop;
2711 else
2712 return;
2713 end if;
2714 /*
2715 Initialize the rule counts. currentConditionRuleCounts is indexed by condition ID for
2716 efficiency (the alternative requires a lot more looping).
2717 */
2718 tempHighestRuleCount := 0;
2719 tempIndex := currentACUsageConditionIds.first;
2720 while(tempIndex is not null) loop
2721 tempConditionId := currentACUsageConditionIds(tempIndex);
2722 if(currentConditionRuleCounts.exists(tempConditionId)) then
2723 currentConditionRuleCounts(tempConditionId) := currentConditionRuleCounts(tempConditionId) + 1;
2724 else
2725 currentConditionRuleCounts(tempConditionId) := 1;
2726 end if;
2727 tempIndex := currentACUsageConditionIds.next(tempIndex);
2728 end loop;
2729 /* Loop through the condition usages. */
2730 while(currentACUsageConditionIds.count > 0) loop
2731 /* Set tempHighestRuleCount. */
2732 tempHighestRuleCount := 0;
2733 tempIndex := currentConditionRuleCounts.first;
2734 while(tempIndex is not null) loop
2735 if(tempHighestRuleCount < currentConditionRuleCounts(tempIndex)) then
2736 tempHighestRuleCount := currentConditionRuleCounts(tempIndex);
2737 tempConditionId := tempIndex;
2738 end if;
2739 tempIndex := currentConditionRuleCounts.next(tempIndex);
2740 end loop;
2741 /* Clear the pending-rule list. */
2742 tempPendingRuleIds.delete;
2743 /*
2744 Choose the first condition with a maximal rule count. Recall that
2745 currentConditionRuleCounts is indexed by condition ID.
2746 */
2747 /* Following while loop commented asper Issue 14 Please refer the */
2748 /* comments in doWeakHeaderEvaluation */
2749 /* tempConditionId := currentConditionRuleCounts.first;
2750 while(tempConditionId is not null) loop
2751 if(currentConditionRuleCounts(tempConditionId) = tempHighestRuleCount) then
2752 exit;
2753 end if;
2754 tempConditionId := currentConditionRuleCounts.next(tempConditionId);
2755 end loop; */
2756 /* From now on, tempConditionId is the ID of the chosen condition with maximal rule count. */
2757 /* Delete this condition from currentConditionRuleCounts. */
2758 currentConditionRuleCounts.delete(tempConditionId);
2759 /*
2760 Evaluate the chosen condition. Note that whether or not the condition is satisfied, the
2761 code first loops through the currentAC variables, locating each currentAC instance matching
2762 the chosen condition. The code avoids compressing the two cases' loops into a single loop
2763 to avoid repeatedly branching on a boolean variable inside the loops, for efficiency.
2764 */
2765 if(conditionIsSatisfied(conditionIdIn => tempConditionId,
2766 itemClassIdIn => itemClassIdIn,
2767 itemIndexIn => itemIndexIn)) then
2768 /*
2769 Remove all usages of this condition from the current condition-usage list, adding their
2770 rules to the pending-rule list. tempIndex indexes the next currentAC variables.
2771 tempIndex2 indexes the current currentAC variables, which may be deleted. tempIndex3
2772 indexes tempPendingRuleIds.
2773 */
2774 tempIndex := currentACUsageConditionIds.first;
2775 tempIndex3 := 0; /* pre-increment */
2776 while(tempIndex is not null) loop
2777 tempIndex2 := tempIndex;
2778 tempIndex := currentACUsageConditionIds.next(tempIndex);
2779 if(currentACUsageConditionIds(tempIndex2) = tempConditionId) then
2780 tempIndex3 := tempIndex3 + 1;
2781 tempPendingRuleIds(tempIndex3) := currentACUsageRuleIds(tempIndex2);
2782 currentACUsageConditionIds.delete(tempIndex2);
2783 currentACUsageRuleIds.delete(tempIndex2);
2784 end if;
2785 end loop;
2786 /* If a pending rule has no other usages, add it to the applicable-rules list. */
2787 for pendingRuleIndex in 1 .. tempPendingRuleIds.count loop
2788 tempRuleApplies := true;
2789 tempIndex := currentACUsageConditionIds.first;
2790 while(tempIndex is not null) loop
2791 if(currentACUsageRuleIds(tempIndex) = tempPendingRuleIds(pendingRuleIndex)) then
2792 tempRuleApplies := false;
2793 exit;
2794 end if;
2795 tempIndex := currentACUsageConditionIds.next(tempIndex);
2796 end loop;
2797 if(tempRuleApplies) then
2798 tempIndex2 := engAppRuleIds.count + 1;
2799 tempRuleId := tempPendingRuleIds(pendingRuleIndex);
2800 engAppRuleIds(tempIndex2) := tempRuleId;
2801 engAppRuleTypes(tempIndex2) := engACUsageRuleTypes(tempRuleId);
2802 engRuleAppliedYN(tempIndex2) := ame_util.booleanTrue;
2803 engAppPriorities(tempIndex2) := engACUsageRulePriorities(tempRuleId);
2804 engAppApproverCategories(tempIndex2) := engACUsageRuleApprCategories(tempRuleId);
2805 engAppItemClassIds(tempIndex2) := itemClassIdIn;
2806 engAppItemIds(tempIndex2) := engItemIds(itemIndexIn);
2807 /*
2808 doPerItemRuleEvaluation only evaluates subordinate-item-class rules, so here
2809 engAppRuleItemClassIds(i) = engAppItemClassIds(i) and
2810 engAppAppItemIds(i) = engAppItemIds(i)
2811 always.
2812 */
2813 engAppRuleItemClassIds(tempIndex2) := itemClassIdIn;
2814 engAppAppItemIds(tempIndex2) := engItemIds(itemIndexIn);
2815 end if;
2816 end loop;
2817 else /* The condition is not satisfied. */
2818 /* Find all rules using the chosen condition. */
2819 tempIndex := currentACUsageConditionIds.first;
2820 tempIndex2 := 0; /* tempIndex2 indexes tempPendingRuleIds; pre-increment it. */
2821 while(tempIndex is not null) loop
2822 if(currentACUsageConditionIds(tempIndex) = tempConditionId) then
2823 tempIndex2 := tempIndex2 + 1;
2824 tempPendingRuleIds(tempIndex2) := currentACUsageRuleIds(tempIndex);
2825 end if;
2826 tempIndex := currentACUsageConditionIds.next(tempIndex);
2827 end loop;
2828 /*
2829 Remove all usages for rules using the chosen condition. If the usage is for
2830 a condition other than the chosen condition, decrement that condition's
2831 rule count. Here tempIndex indexes the next currentAC variable; tempIndex2
2832 indexes the current currentAC variable, which may be deleted; and tempIndex3
2833 indexes the engApp variables.
2834 */
2835 for pendingRuleIndex in 1 .. tempPendingRuleIds.count loop
2836 tempIndex := currentACUsageConditionIds.first;
2837 while(tempIndex is not null) loop
2838 tempIndex2 := tempIndex;
2839 tempIndex := currentACUsageConditionIds.next(tempIndex);
2840 if(currentACUsageRuleIds(tempIndex2) = tempPendingRuleIds(pendingRuleIndex)) then
2841 tempConditionId2 := currentACUsageConditionIds(tempIndex2);
2842 if(tempConditionId2 <> tempConditionId) then
2843 currentConditionRuleCounts(tempConditionId2) := currentConditionRuleCounts(tempConditionId2) - 1;
2844 end if;
2845 currentACUsageConditionIds.delete(tempIndex2);
2846 currentACUsageRuleIds.delete(tempIndex2);
2847 end if;
2848 end loop;
2849 end loop;
2850 end if;
2851 end loop;
2852 exception
2853 when others then
2854 ame_util.runtimeException(packageNameIn => 'ame_engine',
2855 routineNameIn => 'doPerItemRuleEvaluation',
2856 exceptionNumberIn => sqlcode,
2857 exceptionStringIn => sqlerrm);
2858 raise;
2859 end doPerItemRuleEvaluation;
2860 procedure doStrictHeaderRuleEvaluation(itemClassIndexIn in integer,
2861 itemClassIdIn in integer) as
2862 currentACUsageConditionIds ame_util.idList;
2863 currentACUsageRuleIds ame_util.idList;
2864 headerItemIndex integer;
2865 tempFirstRuleIndex integer;
2866 tempLastRuleIndex integer;
2867 tempIndex integer;
2868 tempIndex2 integer;
2869 tempItemClassId integer;
2870 tempItemClassIndex integer;
2871 tempItemId ame_util.stringType;
2872 tempLowerLimit integer;
2873 tempRuleApplies boolean;
2874 tempRuleId integer;
2875 tempRuleId2 integer;
2876 tempUpperLimit integer;
2877 begin
2878 /* Handle the null case (no active conditions) first. */
2879 if(not engACUsageFirstIndexes.exists(itemClassIdIn)) then
2880 return;
2881 end if;
2882 /*
2883 A header-level rule can have conditions on attributes of at most one subordinate
2884 item class. The active condition usages are sorted first by item class, then
2885 by rule ID; so within this procedure, the header item class' active condition
2886 usages are sorted by rule ID. This procedure therefore loops through the rules
2887 in the active condition usages one rule at a time. For each rule, if any of the
2888 conditions is defined on an attribute of a subordinate item class, the procedure
2889 loops through the items of that class, looking for an item that satisfies all of
2890 the rule's subordinate-item-level conditions.
2891 */
2892 /* Initialize the current condition usages. */
2893 tempIndex := 0; /* pre-increment */
2894 for ACUIndex in
2895 engACUsageFirstIndexes(itemClassIdIn) ..
2896 (engACUsageFirstIndexes(itemClassIdIn) + engACUsageItemClassCounts(itemClassIdIn) - 1) loop
2897 tempIndex := tempIndex + 1;
2898 currentACUsageConditionIds(tempIndex) := engACUsageConditionIds(ACUIndex);
2899 currentACUsageRuleIds(tempIndex) := engACUsageRuleIds(ACUIndex);
2900 end loop;
2901 if(currentACUsageRuleIds.count = 0) then
2902 /* There are no condition usages to process, so just return. */
2903 return;
2904 end if;
2905 headerItemIndex := engItemClassItemIdIndexes(itemClassIndexIn);
2906 tempFirstRuleIndex := 1;
2907 /* The following value of tempIndex is used throughout the remainder of the code; don't change it. */
2908 tempIndex := currentACUsageRuleIds.count;
2909 while(tempFirstRuleIndex is not null) loop
2910 tempRuleId := currentACUsageRuleIds(tempFirstRuleIndex);
2911 /* Find the last current condition usage with the rule ID tempRuleId. */
2912 tempLastRuleIndex := tempFirstRuleIndex;
2913 while(tempLastRuleIndex < tempIndex and
2914 currentACUsageRuleIds(tempLastRuleIndex + 1) = tempRuleId) loop
2915 tempLastRuleIndex := tempLastRuleIndex + 1;
2916 end loop;
2917 /*
2918 Determine whether the current rule references any conditions on attributes belonging
2919 to a subordinate item class. If so, all such conditions are on the same item class,
2920 and tempItemClassId is its index. Otherwise, tempItemClassId identifies the header
2921 item class, and tempItemId identifies the header item.
2922 */
2923 tempItemClassId := itemClassIdIn;
2924 tempItemId := engTransactionId;
2925 for ruleIndex in tempFirstRuleIndex .. tempLastRuleIndex loop
2926 tempItemClassId := engAttributeItemClassIds(engACAttributeIds(currentACUsageConditionIds(ruleIndex)));
2927 if(tempItemClassId <> itemClassIdIn) then
2928 exit;
2929 end if;
2930 end loop;
2931 tempRuleApplies := true;
2932 /* First loop through the header-level conditions. */
2933 for ruleIndex in tempFirstRuleIndex .. tempLastRuleIndex loop
2934 if(engAttributeItemClassIds(engACAttributeIds(currentACUsageConditionIds(ruleIndex))) = itemClassIdIn and
2935 not conditionIsSatisfied(conditionIdIn => currentACUsageConditionIds(ruleIndex),
2936 itemClassIdIn => itemClassIdIn,
2937 itemIndexIn => headerItemIndex)) then
2938 tempRuleApplies := false;
2939 exit;
2940 end if;
2941 end loop;
2942 /*
2943 If the rule still applies and at least one condition is defined on a subordinate-item-level
2944 attribute, loop through the subordinate items, looking for an item that satisfies all of the
2945 rule's subordinate-item-level conditions.
2946 */
2947 if(tempRuleApplies and
2948 tempItemClassId <> itemClassIdIn) then
2949 tempItemClassIndex := engItemClassIndexes(tempItemClassId);
2950 tempLowerLimit := engItemClassItemIdIndexes(tempItemClassIndex);
2951 tempRuleApplies := false;
2952 /*
2953 If tempLowerLimit is null, no items exist in this item class, so the rule's conditions
2954 on attributes defined on the item class cannot be satisfied. In this case, tempRuleApplies
2955 stays false.
2956 */
2957 if(tempLowerLimit is not null) then
2958 tempUpperLimit := (engItemClassItemIdIndexes(tempItemClassIndex) + engItemCounts(tempItemClassIndex) - 1);
2959 for itemIndex in tempLowerLimit .. tempUpperLimit loop
2960 for ruleIndex in tempFirstRuleIndex .. tempLastRuleIndex loop
2961 if(engAttributeItemClassIds(engACAttributeIds(currentACUsageConditionIds(ruleIndex))) =
2962 tempItemClassId) then
2963 if(conditionIsSatisfied(conditionIdIn => currentACUsageConditionIds(ruleIndex),
2964 itemClassIdIn => tempItemClassId,
2965 itemIndexIn => itemIndex)) then
2966 /* The rule is only satisfied if all the conditions have succeeded. */
2967 if(ruleIndex = tempLastRuleIndex) then
2968 tempRuleApplies := true;
2969 tempItemId := engItemIds(itemIndex);
2970 exit;
2971 end if;
2972 else
2973 /*
2974 The condition is not satisfied, so the current item does not satisfy the rule.
2975 Leave tempRuleApplies false and exit the inner loop.
2976 */
2977 exit;
2978 end if;
2979 end if;
2980 end loop;
2981 if(tempRuleApplies) then
2982 exit;
2983 end if;
2984 end loop;
2985 end if;
2986 end if;
2987 /* If the rule applies, write it to the applicable-rule package variables. */
2988 if(tempRuleApplies) then
2989 tempIndex2 := engAppRuleIds.count + 1;
2990 tempRuleId2 := currentACUsageRuleIds(tempFirstRuleIndex);
2991 engAppRuleIds(tempIndex2) := tempRuleId2;
2992 engAppRuleTypes(tempIndex2) := engACUsageRuleTypes(tempRuleId2);
2993 engRuleAppliedYN(tempIndex2) := ame_util.booleanTrue;
2994 engAppPriorities(tempIndex2) := engACUsageRulePriorities(tempRuleId2);
2995 engAppApproverCategories(tempIndex2) := engACUsageRuleApprCategories(tempRuleId2);
2996 /* These two variables indicate which item satisfied the rule. */
2997 engAppItemClassIds(tempIndex2) := tempItemClassId;
2998 engAppItemIds(tempIndex2) := tempItemId;
2999 /* These two variables indicate which item the rule applies to, i.e. the header item. */
3000 engAppRuleItemClassIds(tempIndex2) := itemClassIdIn;
3001 engAppAppItemIds(tempIndex2) := engTransactionId;
3002 end if;
3003 /* Iterate or exit the main loop. */
3004 if(tempLastRuleIndex < tempIndex) then
3005 tempFirstRuleIndex := tempLastRuleIndex + 1;
3006 else
3007 exit;
3008 end if;
3009 end loop;
3010 exception
3011 when others then
3012 ame_util.runtimeException(packageNameIn => 'ame_engine',
3013 routineNameIn => 'doStrictHeaderRuleEvaluation',
3014 exceptionNumberIn => sqlcode,
3015 exceptionStringIn => sqlerrm);
3016 raise;
3017 end doStrictHeaderRuleEvaluation;
3018 procedure doWeakHeaderRuleEvaluation(itemClassIndexIn in integer,
3019 itemClassIdIn in integer) as
3020 currentACUsageConditionIds ame_util.idList;
3021 currentACUsageRuleIds ame_util.idList;
3022 currentConditionRuleCounts ame_util.idList;
3023 tempAttributeItemClassIndex integer;
3024 tempConditionId integer;
3025 tempConditionId2 integer;
3026 tempConditionIsSatisfied boolean;
3027 tempHighestRuleCount integer;
3028 tempIndex integer;
3029 tempIndex2 integer;
3030 tempIndex3 integer;
3031 tempLowerLimit integer;
3032 tempPendingRuleIds ame_util.idList;
3033 tempRuleApplies boolean;
3034 tempRuleId integer;
3035 tempUpperLimit integer;
3036 begin
3037 /* Handle the null case (no active conditions) first. */
3038 if(not engACUsageFirstIndexes.exists(itemClassIdIn)) then
3039 return;
3040 end if;
3041 /*
3042 Initialize the current condition usages. Note that while the currentACUsage local
3043 variables start out as compact lists, the algorithm that iterates through them
3044 deletes them in an unpredictable order, and does not re-compact the lists; so the
3045 algorithm must treat these lists as sparse.
3046 */
3047 tempIndex := 0; /* pre-increment */
3048 for ACUIndex in
3049 engACUsageFirstIndexes(itemClassIdIn) ..
3050 (engACUsageFirstIndexes(itemClassIdIn) + engACUsageItemClassCounts(itemClassIdIn) - 1) loop
3051 tempIndex := tempIndex + 1;
3052 currentACUsageConditionIds(tempIndex) := engACUsageConditionIds(ACUIndex);
3053 currentACUsageRuleIds(tempIndex) := engACUsageRuleIds(ACUIndex);
3054 end loop;
3055 /*
3056 Initialize the rule counts. currentConditionRuleCounts is indexed by condition ID for
3057 efficiency (the alternative requires a lot more looping).
3058 */
3059 tempIndex := currentACUsageConditionIds.first;
3060 while(tempIndex is not null) loop
3061 tempConditionId := currentACUsageConditionIds(tempIndex);
3062 if(currentConditionRuleCounts.exists(tempConditionId)) then
3063 currentConditionRuleCounts(tempConditionId) := currentConditionRuleCounts(tempConditionId) + 1;
3064 else
3065 currentConditionRuleCounts(tempConditionId) := 1;
3066 end if;
3067 tempIndex := currentACUsageConditionIds.next(tempIndex);
3068 end loop;
3069 /* Loop through the condition usages. */
3070 while(currentACUsageConditionIds.count > 0) loop
3071 /* Set tempHighestRuleCount. */
3072 tempHighestRuleCount := 0;
3073 tempIndex := currentConditionRuleCounts.first;
3074 while(tempIndex is not null) loop
3075 if(tempHighestRuleCount < currentConditionRuleCounts(tempIndex)) then
3076 tempHighestRuleCount := currentConditionRuleCounts(tempIndex);
3077 /* Following line has been added to avoid the another while loop to */
3078 /* find the condition with highest rule count. Issue 14 of the bug list */
3079 /* No bug logged for this */
3080 /* currentConditionRuleCounts is pl/sql list which is sparse and indexes */
3081 /* are nothig but condition_ids.Hence there is no need to find the */
3082 /* condition_id which has highestRuleCount in another loop.after this */
3083 /* while loop the tempConditionId is the condition with highestRuleCount.*/
3084 tempConditionId := tempIndex;
3085 end if;
3086 tempIndex := currentConditionRuleCounts.next(tempIndex);
3087 end loop;
3088 /* Clear the pending-rule list. */
3089 tempPendingRuleIds.delete;
3090 /*
3091 Choose the first condition with a maximal rule count. Recall that currentConditionRuleCounts
3092 is indexed by condition ID.
3093 */
3094 /* Removing this while loop as we already know the condition with */
3095 /* highest rule count */
3096 /* tempConditionId := currentConditionRuleCounts.first;
3097 while(tempConditionId is not null) loop
3098 if(currentConditionRuleCounts(tempConditionId) = tempHighestRuleCount) then
3099 exit;
3100 end if;
3101 tempConditionId := currentConditionRuleCounts.next(tempConditionId);
3102 end loop;*/
3103 /* From now on, tempConditionId is the ID of the chosen condition with maximal rule count. */
3104 /* Delete this condition from currentConditionRuleCounts. */
3105 currentConditionRuleCounts.delete(tempConditionId);
3106 /*
3107 Test the condition for each item in the item class of the attribute on which the condition
3108 is defined, until an item satisfies the condition or no items are left.
3109 */
3110 tempAttributeItemClassIndex :=
3111 engItemClassIndexes(engAttributeItemClassIds(engACAttributeIds(tempConditionId)));
3112 tempConditionIsSatisfied := false;
3113 tempLowerLimit := engItemClassItemIdIndexes(tempAttributeItemClassIndex);
3114 if(tempLowerLimit is not null) then
3115 tempUpperLimit :=
3116 (engItemClassItemIdIndexes(tempAttributeItemClassIndex) + engItemCounts(tempAttributeItemClassIndex) - 1);
3117 for itemIndex in tempLowerLimit .. tempUpperLimit loop
3118 if(conditionIsSatisfied(conditionIdIn => tempConditionId,
3119 itemClassIdIn => engAttributeItemClassIds(engACAttributeIds(tempConditionId)),
3120 itemIndexIn => itemIndex)) then
3121 tempConditionIsSatisfied := true;
3122 exit;
3123 end if;
3124 end loop;
3125 end if;
3126 /*
3127 If the condition is satisfied, eliminate its usages, and add any rules with no other
3128 usages to the applicable-rules list. If the condition is not satisfied, just eliminate
3129 its usages, and any other usages for the rules in the condition's usages.
3130 */
3131 if(tempConditionIsSatisfied) then
3132 /*
3133 Remove all usages of this condition from the current condition-usage list, adding their
3134 rules to the pending-rule list. tempIndex indexes the next currentAC variables.
3135 tempIndex2 indexes the current currentAC variables, which may be deleted. tempIndex3
3136 indexes tempPendingRuleIds.
3137 */
3138 tempIndex := currentACUsageConditionIds.first;
3139 tempIndex3 := 0; /* pre-increment */
3140 while(tempIndex is not null) loop
3141 tempIndex2 := tempIndex;
3142 tempIndex := currentACUsageConditionIds.next(tempIndex);
3143 if(currentACUsageConditionIds(tempIndex2) = tempConditionId) then
3144 tempIndex3 := tempIndex3 + 1;
3145 tempPendingRuleIds(tempIndex3) := currentACUsageRuleIds(tempIndex2);
3146 currentACUsageConditionIds.delete(tempIndex2);
3147 currentACUsageRuleIds.delete(tempIndex2);
3148 end if;
3149 end loop;
3150 /* If a pending rule has no other usages, add it to the applicable-rules list. */
3151 for pendingRuleIndex in 1 .. tempPendingRuleIds.count loop
3152 tempRuleApplies := true;
3153 tempIndex := currentACUsageConditionIds.first;
3154 while(tempIndex is not null) loop
3155 if(currentACUsageRuleIds(tempIndex) = tempPendingRuleIds(pendingRuleIndex)) then
3156 tempRuleApplies := false;
3157 exit;
3158 end if;
3159 tempIndex := currentACUsageConditionIds.next(tempIndex);
3160 end loop;
3161 if(tempRuleApplies) then
3162 tempIndex2 := engAppRuleIds.count + 1;
3163 tempRuleId := tempPendingRuleIds(pendingRuleIndex);
3164 engAppRuleIds(tempIndex2) := tempRuleId;
3165 engAppRuleTypes(tempIndex2) := engACUsageRuleTypes(tempRuleId);
3166 engRuleAppliedYN(tempIndex2) := ame_util.booleanTrue;
3167 engAppPriorities(tempIndex2) := engACUsageRulePriorities(tempRuleId);
3168 engAppApproverCategories(tempIndex2) := engACUsageRuleApprCategories(tempRuleId);
3169 engAppItemClassIds(tempIndex2) := itemClassIdIn;
3170 engAppItemIds(tempIndex2) := engTransactionId;
3171 /* In this case the satisfying item and item to which the rule applies always match. */
3172 engAppRuleItemClassIds(tempIndex2) := engAppItemClassIds(tempIndex2);
3173 engAppAppItemIds(tempIndex2) := engAppItemIds(tempIndex2);
3174 end if;
3175 end loop;
3176 else /* The condition is not satisfied. */
3177 /* Put all rules using the chosen condition in the pending-rule list. */
3178 tempIndex := currentACUsageConditionIds.first;
3179 tempIndex2 := 0; /* tempIndex2 indexes tempPendingRuleIds; pre-increment it. */
3180 while(tempIndex is not null) loop
3181 if(currentACUsageConditionIds(tempIndex) = tempConditionId) then
3182 tempIndex2 := tempIndex2 + 1;
3183 tempPendingRuleIds(tempIndex2) := currentACUsageRuleIds(tempIndex);
3184 end if;
3185 tempIndex := currentACUsageConditionIds.next(tempIndex);
3186 end loop;
3187 /*
3188 Remove all usages for rules using the chosen condition. If the usage is for
3189 a condition other than the chosen condition, decrement that condition's
3190 rule count. Here tempIndex indexes the next currentAC variable, and tempIndex2
3191 indexes the current currentAC variable (which may be deleted).
3192 */
3193 for pendingRuleIndex in 1 .. tempPendingRuleIds.count loop
3194 tempIndex := currentACUsageConditionIds.first;
3195 while(tempIndex is not null) loop
3196 tempIndex2 := tempIndex;
3197 tempIndex := currentACUsageConditionIds.next(tempIndex);
3198 if(currentACUsageRuleIds(tempIndex2) = tempPendingRuleIds(pendingRuleIndex)) then
3199 tempConditionId2 := currentACUsageConditionIds(tempIndex2);
3200 if(tempConditionId2 <> tempConditionId) then
3201 currentConditionRuleCounts(tempConditionId2) := currentConditionRuleCounts(tempConditionId2) - 1;
3202 end if;
3203 currentACUsageConditionIds.delete(tempIndex2);
3204 currentACUsageRuleIds.delete(tempIndex2);
3205 end if;
3206 end loop;
3207 end loop;
3208 end if;
3209 end loop;
3210 exception
3211 when others then
3212 ame_util.runtimeException(packageNameIn => 'ame_engine',
3213 routineNameIn => 'doWeakHeaderRuleEvaluation',
3214 exceptionNumberIn => sqlcode,
3215 exceptionStringIn => sqlerrm);
3216 raise;
3217 end doWeakHeaderRuleEvaluation;
3218 procedure evaluateRules as
3219 /*
3220 conditionlessRuleCursor finds all rules having no ordinary or exception conditions
3221 that the current transaction type uses.
3222 */
3223 cursor conditionlessRuleCursor(processPrioritiesIn in varchar2,
3224 processProductionRulesIn in varchar2,
3225 combinationRulePriorityModeIn in varchar2,
3226 combinationRuleThresholdIn in integer,
3227 authorityRulePriorityModeIn in varchar2,
3228 authorityRuleThresholdIn in integer,
3229 exceptionRulePriorityModeIn in varchar2,
3230 exceptionRuleThresholdIn in integer,
3231 listModRulePriorityModeIn in varchar2,
3232 listModRuleThresholdIn in integer,
3233 substRulePriorityModeIn in varchar2,
3234 substRuleThresholdIn in integer,
3235 preRulePriorityModeIn in varchar2,
3236 preRuleThresholdIn in integer,
3237 postRulePriorityModeIn in varchar2,
3238 postRuleThresholdIn in integer,
3239 productionRulePriorityModeIn in varchar2,
3240 productionRuleThresholdIn in integer,
3241 headerItemClassIdIn in integer) is
3242 select
3243 ame_rules.rule_id rule_id,
3244 nvl(ame_rules.item_class_id,
3245 headerItemClassIdIn) item_class_id,
3246 ame_rules.rule_type rule_type,
3247 ame_rule_usages.priority priority,
3248 ame_rule_usages.approver_category approver_category
3249 from
3250 ame_rules,
3251 ame_rule_usages,
3252 ame_item_class_usages
3253 where
3254 ame_rules.rule_id = ame_rule_usages.rule_id and
3255 ame_rule_usages.item_id = engAmeApplicationId and
3256 nvl(ame_rules.item_class_id, headerItemClassIdIn) = ame_item_class_usages.item_class_id and
3257 ame_item_class_usages.application_id = engAmeApplicationId and
3258 (processPrioritiesIn = ame_util.booleanFalse or
3259 (ame_rules.rule_type = ame_util.combinationRuleType and
3260 (combinationRulePriorityModeIn <> ame_util.absoluteRulePriority or
3261 combinationRuleThresholdIn >= ame_rule_usages.priority)) or
3262 (ame_rules.rule_type = ame_util.authorityRuleType and
3263 (authorityRulePriorityModeIn <> ame_util.absoluteRulePriority or
3264 authorityRuleThresholdIn >= ame_rule_usages.priority)) or
3265 (ame_rules.rule_type = ame_util.exceptionRuleType and
3266 (exceptionRulePriorityModeIn <> ame_util.absoluteRulePriority or
3267 exceptionRuleThresholdIn >= ame_rule_usages.priority)) or
3268 (ame_rules.rule_type = ame_util.listModRuleType and
3269 (listModRulePriorityModeIn <> ame_util.absoluteRulePriority or
3270 listModRuleThresholdIn >= ame_rule_usages.priority)) or
3271 (ame_rules.rule_type = ame_util.substitutionRuleType and
3272 (substRulePriorityModeIn <> ame_util.absoluteRulePriority or
3273 substRuleThresholdIn >= ame_rule_usages.priority)) or
3274 (ame_rules.rule_type = ame_util.preListGroupRuleType and
3275 (preRulePriorityModeIn <> ame_util.absoluteRulePriority or
3276 preRuleThresholdIn >= ame_rule_usages.priority)) or
3277 (ame_rules.rule_type = ame_util.postListGroupRuleType and
3278 (postRulePriorityModeIn <> ame_util.absoluteRulePriority or
3279 postRuleThresholdIn >= ame_rule_usages.priority)) or
3280 (ame_rules.rule_type = ame_util.productionRuleType and
3281 (productionRulePriorityModeIn <> ame_util.absoluteRulePriority or
3282 productionRuleThresholdIn >= ame_rule_usages.priority))) and
3283 (processProductionRulesIn = ame_util.booleanTrue or
3284 ame_rules.rule_type <> ame_util.productionRuleType) and
3285 not exists (select *
3286 from
3287 ame_conditions,
3288 ame_condition_usages
3289 where
3290 ame_conditions.condition_type <> ame_util.listModConditionType and
3291 ame_conditions.condition_id = ame_condition_usages.condition_id and
3292 ame_condition_usages.rule_id = ame_rules.rule_id and
3293 engEffectiveRuleDate between
3294 ame_conditions.start_date and
3295 nvl(ame_conditions.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3296 engEffectiveRuleDate between
3297 ame_condition_usages.start_date and
3298 nvl(ame_condition_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3299 /* Avoids second fetch otherwise required by ANSI standard to check for too many rows. */
3300 rownum < 2) and
3301 engEffectiveRuleDate between
3302 ame_rules.start_date and
3303 nvl(ame_rules.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3304 engEffectiveRuleDate between
3305 ame_rule_usages.start_date and
3306 nvl(ame_rule_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3307 engEffectiveRuleDate between
3308 ame_item_class_usages.start_date and
3309 nvl(ame_item_class_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate)
3310 order by
3311 ame_item_class_usages.item_class_order_number,
3312 item_class_id,
3313 ame_rules.rule_type,
3314 ame_rules.rule_id;
3315 conditionlessItemClassIds ame_util.idList;
3316 conditionlessRuleApprCats ame_util.charList;
3317 conditionlessRuleIds ame_util.idList;
3318 conditionlessRulePriorities ame_util.idList;
3319 conditionlessRuleTypes ame_util.stringList;
3320 errorCode integer;
3321 errorMessage ame_util.longestStringType;
3322 firstConditionlessRuleFound boolean;
3323 firstConditionlessRuleIndex integer;
3324 lastConditionlessRuleIndex integer;
3325 lowerBound integer;
3326 noRulesException exception;
3327 processPriorities ame_util.charType;
3328 processProductions ame_util.charType;
3329 tempIndex integer;
3330 tempItemClassId integer;
3331 upperBound integer;
3332 upperBound2 integer;
3333 begin
3334 /* Fetch all conditionless rules and store them in local variables. */
3335 if(engProcessPriorities) then
3336 processPriorities := ame_util.booleanTrue;
3337 else
3338 processPriorities := ame_util.booleanFalse;
3339 end if;
3340 if(engProcessProductionRules) then
3341 processProductions := ame_util.booleanTrue;
3342 else
3343 processProductions := ame_util.booleanFalse;
3344 end if;
3345 open conditionlessRuleCursor(processPrioritiesIn => processPriorities,
3346 processProductionRulesIn => processProductions,
3347 combinationRulePriorityModeIn => engPriorityModes(ame_util.combinationRuleType),
3348 combinationRuleThresholdIn => engPriorityThresholds(ame_util.combinationRuleType),
3349 authorityRulePriorityModeIn => engPriorityModes(ame_util.authorityRuleType),
3350 authorityRuleThresholdIn => engPriorityThresholds(ame_util.authorityRuleType),
3351 exceptionRulePriorityModeIn => engPriorityModes(ame_util.exceptionRuleType),
3352 exceptionRuleThresholdIn => engPriorityThresholds(ame_util.exceptionRuleType),
3353 listModRulePriorityModeIn => engPriorityModes(ame_util.listModRuleType),
3354 listModRuleThresholdIn => engPriorityThresholds(ame_util.listModRuleType),
3355 substRulePriorityModeIn => engPriorityModes(ame_util.substitutionRuleType),
3356 substRuleThresholdIn => engPriorityThresholds(ame_util.substitutionRuleType),
3357 preRulePriorityModeIn => engPriorityModes(ame_util.preListGroupRuleType),
3358 preRuleThresholdIn => engPriorityThresholds(ame_util.preListGroupRuleType),
3359 postRulePriorityModeIn => engPriorityModes(ame_util.postListGroupRuleType),
3360 postRuleThresholdIn => engPriorityThresholds(ame_util.postListGroupRuleType),
3361 productionRulePriorityModeIn => engPriorityModes(ame_util.productionRuleType),
3362 productionRuleThresholdIn => engPriorityThresholds(ame_util.productionRuleType),
3363 headerItemClassIdIn => getItemClassId(itemClassNameIn => ame_util.headerItemClassName));
3364 fetch conditionlessRuleCursor bulk collect
3365 into
3366 conditionlessRuleIds,
3367 conditionlessItemClassIds,
3368 conditionlessRuleTypes,
3369 conditionlessRulePriorities,
3370 conditionlessRuleApprCats;
3371 close conditionlessRuleCursor;
3372 firstConditionlessRuleIndex := 0;
3373 lastConditionlessRuleIndex := 0;
3374 /*
3375 Loop through the item classes in engItemClassIds, evaluating the
3376 transaction type's rules for each item in each class.
3377 */
3378 for itemClassIndex in 1 .. engItemClassIds.count loop
3379 lowerBound := engItemClassItemIdIndexes(itemClassIndex);
3380 if(lowerBound is not null) then
3381 upperBound := engItemClassItemIdIndexes(itemClassIndex) + engItemCounts(itemClassIndex) - 1;
3382 tempItemClassId := engItemClassIds(itemClassIndex);
3383 /* Find this item class' conditionless rules. */
3384 firstConditionlessRuleFound := false;
3385 upperBound2 := conditionlessRuleIds.count;
3386 /* Following for loop modified for bug 4094058 Issue 19 */
3387 for i in firstConditionlessRuleIndex + 1 .. upperBound2 loop
3388 if(firstConditionlessRuleFound) then
3389 if(conditionlessItemClassIds(i) = tempItemClassId) then
3390 lastConditionlessRuleIndex := i;
3391 end if;
3392 else
3393 if(conditionlessItemClassIds(i) = tempItemClassId) then
3394 firstConditionlessRuleFound := true;
3395 firstConditionlessRuleIndex := i;
3396 lastConditionlessRuleIndex := i;
3397 end if;
3398 end if;
3399 if (i < upperBound2 and conditionlessItemClassIds(i+1) <> tempItemClassId) then
3400 exit;
3401 end if;
3402 end loop;
3403 /* Loop through the items in this item class. */
3404 for itemIndex in lowerBound .. upperBound loop
3405 /* Add any conditionless rules for the current item class to the current item's applicable-rule list. */
3406 if(firstConditionlessRuleFound) then
3407 tempIndex := engAppRuleIds.count; /* pre-increment */
3408 for conditionlessRuleIndex in firstConditionlessRuleIndex .. lastConditionlessRuleIndex loop
3409 tempIndex := tempIndex + 1;
3410 engAppRuleIds(tempIndex) := conditionlessRuleIds(conditionlessRuleIndex);
3411 engAppPriorities(tempIndex) := conditionlessRulePriorities(conditionlessRuleIndex);
3412 engAppApproverCategories(tempIndex) := conditionlessRuleApprCats(conditionlessRuleIndex);
3413 engAppRuleTypes(tempIndex) := conditionlessRuleTypes(conditionlessRuleIndex);
3414 engRuleAppliedYN(tempIndex) := ame_util.booleanTrue;
3415 /* These are the item class and item to which the rule applies. */
3416 engAppItemClassIds(tempIndex) := tempItemClassId;
3417 engAppItemIds(tempIndex) := engItemIds(itemIndex);
3418 /*
3419 These are the item class and item that satisfy the rule. By convention, for rules
3420 having no ordinary conditions, these are the same as the item class and item to
3421 which the rule applies.
3422 */
3423 engAppRuleItemClassIds(tempIndex) := tempItemClassId;
3424 engAppAppItemIds(tempIndex) := engItemIds(itemIndex);
3425 end loop;
3426 end if;
3427 /* Evaluate the rules with conditions for this item. */
3428 if(engItemClassNames(itemClassIndex) = ame_util.headerItemClassName) then
3429 /*
3430 The header item class always has exactly one item, so one of the procedures
3431 in the following if/else will get called exactly once per engine cycle.
3432 */
3433 if(getHeaderAttValue2(attributeNameIn => ame_util.restrictiveItemEvalAttribute) =
3434 ame_util.booleanAttributeTrue) then
3435 doStrictHeaderRuleEvaluation(itemClassIndexIn => itemClassIndex,
3436 itemClassIdIn => tempItemClassId);
3437 else
3438 doWeakHeaderRuleEvaluation(itemClassIndexIn => itemClassIndex,
3439 itemClassIdIn => tempItemClassId);
3440 end if;
3441 else
3442 /* Evaluate the rules in the active conditions for the current item only. */
3443 doPerItemRuleEvaluation(itemClassIdIn => tempItemClassId,
3444 itemIndexIn => itemIndex);
3445 end if;
3446 end loop;
3447 end if;
3448 end loop;
3449 /*
3450 So far, list-modification and substitution rules have been treated as if they belonged
3451 to the header item class. Now set their item-class IDs and item IDs null and sort the
3452 applicable rules, so the list-modification and substitution rules get processed last.
3453 */
3454 for i in 1 .. engAppRuleIds.count loop
3455 if(engAppRuleTypes(i) in (ame_util.listModRuleType, ame_util.substitutionRuleType)) then
3456 engRuleAppliedYN(i) := ame_util.booleanFalse;
3457 engAppLMSubItemClassIds(engAppRuleIds(i)) := engAppRuleItemClassIds(i);
3458 engAppLMSubItemIds(engAppRuleIds(i)) := engAppAppItemIds(i);
3459 engAppRuleItemClassIds(i) := null;
3460 engAppAppItemIds(i) := null;
3461 end if;
3462 end loop;
3463 sortApplicableRules(sortByActionTypeIn => false);
3464 /*
3465 Priority processing has so far occurred only for absolute priorities--for conditionless
3466 rules in the conditionlessRuleCursor in this procedure, for rule with conditions in the
3467 activeCondUsageCursor cursor of the procedure fetchActiveConditionUsages. Now that the
3468 remaining applicable rules are sorted by rule type, we can process relative priorities.
3469 */
3470 if(engProcessPriorities) then
3471 processRelativePriorities;
3472 end if;
3473 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
3474 if engAppRuleIds.count = 0 then
3475 fnd_log.string
3476 (fnd_log.level_statement
3477 ,'ame_engine.evaluateRules'
3478 ,'*********** No Rules Applicable ************'
3479 );
3480 else
3481 for i in 1 .. engAppRuleIds.count loop
3482 fnd_log.string
3483 (fnd_log.level_statement
3484 ,'ame_engine.evaluateRules'
3485 ,'Applicable Rule ::: ' || engAppRuleIds(i)
3486 );
3487 end loop;
3488 end if;
3489 end if;
3490 /* Check for no rules, if AT_LEAST_ONE_RULE_MUST_APPLY is true. */
3491 if(getHeaderAttValue2(attributeNameIn => ame_util.atLeastOneRuleAttribute) = ame_util.booleanAttributeTrue and
3492 engAppRuleIds.count = 0) then
3493 raise noRulesException;
3494 end if;
3495 exception
3496 when noRulesException then
3497 errorCode := -20102;
3498 errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
3499 messageNameIn => 'AME_400117_ENG_ONE_RULE_APPLY');
3500 ame_util.runtimeException(packageNameIn => 'ame_engine',
3501 routineNameIn => 'evaluateRules',
3502 exceptionNumberIn => errorCode,
3503 exceptionStringIn => errorMessage);
3504 raise_application_error(errorCode,
3505 errorMessage);
3506 when others then
3507 if(conditionlessRuleCursor%isopen) then
3508 close conditionlessRuleCursor;
3509 end if;
3510 ame_util.runtimeException(packageNameIn => 'ame_engine',
3511 routineNameIn => 'evaluateRules',
3512 exceptionNumberIn => sqlcode,
3513 exceptionStringIn => sqlerrm);
3514 raise;
3515 end evaluateRules;
3516 procedure fetchActiveConditionUsages as
3517 cursor activeCondStringValueCursor is
3518 select
3519 condition_id,
3520 string_value
3521 from ame_string_values
3522 where
3523 condition_id in
3524 (select ame_condition_usages.condition_id
3525 from
3526 ame_attributes,
3527 ame_conditions,
3528 ame_condition_usages,
3529 ame_rule_usages
3530 where
3531 ame_attributes.attribute_type = ame_util.stringAttributeType and
3532 ame_attributes.attribute_id = ame_conditions.attribute_id and
3533 ame_conditions.condition_id = ame_condition_usages.condition_id and
3534 ame_condition_usages.rule_id = ame_rule_usages.rule_id and
3535 ame_rule_usages.item_id = engAmeApplicationId and
3536 engEffectiveRuleDate between
3537 ame_attributes.start_date and
3538 nvl(ame_attributes.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3539 engEffectiveRuleDate between
3540 ame_conditions.start_date and
3541 nvl(ame_conditions.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3542 engEffectiveRuleDate between
3543 ame_condition_usages.start_date and
3544 nvl(ame_condition_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3545 engEffectiveRuleDate between
3546 ame_rule_usages.start_date and
3547 nvl(ame_rule_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate)) and
3548 engEffectiveRuleDate between
3549 ame_string_values.start_date and
3550 nvl(ame_string_values.end_date - ame_util.oneSecond, engEffectiveRuleDate)
3551 order by condition_id;
3552 cursor activeCondUsageCursor(processPrioritiesIn in varchar2,
3553 processProductionRulesIn in varchar2,
3554 combinationRulePriorityModeIn in varchar2,
3555 combinationRuleThresholdIn in integer,
3556 authorityRulePriorityModeIn in varchar2,
3557 authorityRuleThresholdIn in integer,
3558 exceptionRulePriorityModeIn in varchar2,
3559 exceptionRuleThresholdIn in integer,
3560 listModRulePriorityModeIn in varchar2,
3561 listModRuleThresholdIn in integer,
3562 substRulePriorityModeIn in varchar2,
3563 substRuleThresholdIn in integer,
3564 preRulePriorityModeIn in varchar2,
3565 preRuleThresholdIn in integer,
3566 postRulePriorityModeIn in varchar2,
3567 postRuleThresholdIn in integer,
3568 productionRulePriorityModeIn in varchar2,
3569 productionRuleThresholdIn in integer,
3570 headerItemClassIdIn in integer) is
3571 select
3572 ame_conditions.condition_id condition_id,
3573 ame_conditions.condition_type condition_type,
3574 ame_conditions.attribute_id attribute_id,
3575 ame_conditions.parameter_one parameter_one,
3576 ame_conditions.parameter_two parameter_two,
3577 ame_conditions.parameter_three parameter_three,
3578 ame_conditions.include_lower_limit,
3579 ame_conditions.include_upper_limit,
3580 ame_condition_usages.rule_id rule_id,
3581 ame_rules.rule_type rule_type,
3582 nvl(ame_rules.item_class_id,
3583 headerItemClassIdIn) rule_item_class,
3584 ame_rule_usages.priority priority,
3585 ame_rule_usages.approver_category
3586 from
3587 ame_attributes,
3588 ame_conditions,
3589 ame_condition_usages,
3590 ame_rules,
3591 ame_rule_usages
3592 where
3593 ame_attributes.attribute_id = ame_conditions.attribute_id and
3594 ame_conditions.condition_type <> ame_util.listModConditionType and
3595 ame_conditions.condition_id = ame_condition_usages.condition_id and
3596 ame_condition_usages.rule_id = ame_rules.rule_id and
3597 ame_rules.rule_id = ame_rule_usages.rule_id and
3598 ame_rule_usages.item_id = engAmeApplicationId and
3599 (processPrioritiesIn = ame_util.booleanFalse or
3600 (ame_rules.rule_type = ame_util.combinationRuleType and
3601 (combinationRulePriorityModeIn <> ame_util.absoluteRulePriority or
3602 combinationRuleThresholdIn >= ame_rule_usages.priority)) or
3603 (ame_rules.rule_type = ame_util.authorityRuleType and
3604 (authorityRulePriorityModeIn <> ame_util.absoluteRulePriority or
3605 authorityRuleThresholdIn >= ame_rule_usages.priority)) or
3606 (ame_rules.rule_type = ame_util.exceptionRuleType and
3607 (exceptionRulePriorityModeIn <> ame_util.absoluteRulePriority or
3608 exceptionRuleThresholdIn >= ame_rule_usages.priority)) or
3609 (ame_rules.rule_type = ame_util.listModRuleType and
3610 (listModRulePriorityModeIn <> ame_util.absoluteRulePriority or
3611 listModRuleThresholdIn >= ame_rule_usages.priority)) or
3612 (ame_rules.rule_type = ame_util.substitutionRuleType and
3613 (substRulePriorityModeIn <> ame_util.absoluteRulePriority or
3614 substRuleThresholdIn >= ame_rule_usages.priority)) or
3615 (ame_rules.rule_type = ame_util.preListGroupRuleType and
3616 (preRulePriorityModeIn <> ame_util.absoluteRulePriority or
3617 preRuleThresholdIn >= ame_rule_usages.priority)) or
3618 (ame_rules.rule_type = ame_util.postListGroupRuleType and
3619 (postRulePriorityModeIn <> ame_util.absoluteRulePriority or
3620 postRuleThresholdIn >= ame_rule_usages.priority)) or
3621 (ame_rules.rule_type = ame_util.productionRuleType and
3622 (productionRulePriorityModeIn <> ame_util.absoluteRulePriority or
3623 productionRuleThresholdIn >= ame_rule_usages.priority))) and
3624 (processProductionRulesIn = ame_util.booleanTrue or
3625 ame_rules.rule_type <> ame_util.productionRuleType) and
3626 engEffectiveRuleDate between
3627 ame_attributes.start_date and
3628 nvl(ame_attributes.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3629 engEffectiveRuleDate between
3630 ame_conditions.start_date and
3631 nvl(ame_conditions.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3632 engEffectiveRuleDate between
3633 ame_condition_usages.start_date and
3634 nvl(ame_condition_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3635 engEffectiveRuleDate between
3636 ame_rules.start_date and
3637 nvl(ame_rules.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3638 engEffectiveRuleDate between
3639 ame_rule_usages.start_date and
3640 nvl(ame_rule_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate)
3641 order by
3642 rule_item_class,
3643 ame_rules.rule_type,
3644 ame_rules.rule_id,
3645 ame_attributes.item_class_id;
3646 /*
3647 The tempACU tables are buffers between the active-condition-usage fetch and
3648 the engAC variables. The temp variables are indexed consecutively, while
3649 the engAC variables are indexed by condition ID or rule ID.
3650 */
3651 tempACUAttributeIds ame_util.idList;
3652 tempACUConditionTypes ame_util.stringList;
3653 tempACUIncludeLowerLimits ame_util.charList;
3654 tempACUIncludeUpperLimits ame_util.charList;
3655 tempACUItemClassIds ame_util.idList;
3656 tempACUParameterOnes ame_util.stringList;
3657 tempACUParameterThrees ame_util.stringList;
3658 tempACUParameterTwos ame_util.longStringList;
3659 tempACURuleApprCats ame_util.charList;
3660 tempACURulePriorities ame_util.idList;
3661 tempACURuleTypes ame_util.idList;
3662 /*
3663 tempACConditionIds is a buffer between the string-value fetch and the
3664 engACStringValue variables.
3665 */
3666 tempACConditionIds ame_util.idList;
3667 /* misc. local variables */
3668 processPriorities ame_util.charType;
3669 processProductions ame_util.charType;
3670 tempConditionID integer;
3671 tempCount integer;
3672 tempItemClassID integer;
3673 tempRuleId integer;
3674 begin
3675 /*
3676 Fetch all condition usages for conditions used by the rules that are used by
3677 the current transaction type.
3678 */
3679 if(engProcessPriorities) then
3680 processPriorities := ame_util.booleanTrue;
3681 else
3682 processPriorities := ame_util.booleanFalse;
3683 end if;
3684 if(engProcessProductionRules) then
3685 processProductions := ame_util.booleanTrue;
3686 else
3687 processProductions := ame_util.booleanFalse;
3688 end if;
3689 open activeCondUsageCursor(processPrioritiesIn => processPriorities,
3690 processProductionRulesIn => processProductions,
3691 combinationRulePriorityModeIn => engPriorityModes(ame_util.combinationRuleType),
3692 combinationRuleThresholdIn => engPriorityThresholds(ame_util.combinationRuleType),
3693 authorityRulePriorityModeIn => engPriorityModes(ame_util.authorityRuleType),
3694 authorityRuleThresholdIn => engPriorityThresholds(ame_util.authorityRuleType),
3695 exceptionRulePriorityModeIn => engPriorityModes(ame_util.exceptionRuleType),
3696 exceptionRuleThresholdIn => engPriorityThresholds(ame_util.exceptionRuleType),
3697 listModRulePriorityModeIn => engPriorityModes(ame_util.listModRuleType),
3698 listModRuleThresholdIn => engPriorityThresholds(ame_util.listModRuleType),
3699 substRulePriorityModeIn => engPriorityModes(ame_util.substitutionRuleType),
3700 substRuleThresholdIn => engPriorityThresholds(ame_util.substitutionRuleType),
3701 preRulePriorityModeIn => engPriorityModes(ame_util.preListGroupRuleType),
3702 preRuleThresholdIn => engPriorityThresholds(ame_util.preListGroupRuleType),
3703 postRulePriorityModeIn => engPriorityModes(ame_util.postListGroupRuleType),
3704 postRuleThresholdIn => engPriorityThresholds(ame_util.postListGroupRuleType),
3705 productionRulePriorityModeIn => engPriorityModes(ame_util.productionRuleType),
3706 productionRuleThresholdIn => engPriorityThresholds(ame_util.productionRuleType),
3707 headerItemClassIdIn => getItemClassId(itemClassNameIn => ame_util.headerItemClassName));
3708 fetch activeCondUsageCursor bulk collect
3709 into
3710 engACUsageConditionIds,
3711 tempACUConditionTypes,
3712 tempACUAttributeIds,
3713 tempACUParameterOnes,
3714 tempACUParameterTwos,
3715 tempACUParameterThrees,
3716 tempACUIncludeLowerLimits,
3717 tempACUIncludeUpperLimits,
3718 engACUsageRuleIds,
3719 tempACURuleTypes,
3720 tempACUItemClassIds,
3721 tempACURulePriorities,
3722 tempACURuleApprCats;
3723 close activeCondUsageCursor;
3724 /*
3725 Loop through the active condition usages, writing their conditions to the
3726 engAC variables each time a new condition is encountered.
3727 */
3728 tempCount := engACUsageConditionIds.count;
3729 for activeCUIndex in 1 .. tempCount loop
3730 tempItemClassID := tempACUItemClassIds(activeCUIndex);
3731 tempConditionID := engACUsageConditionIds(activeCUIndex);
3732 if(not engACAttributeIds.exists(tempConditionID)) then
3733 engACAttributeIds(tempConditionID) := tempACUAttributeIds(activeCUIndex);
3734 engACConditionTypes(tempConditionID) := tempACUConditionTypes(activeCUIndex);
3735 engACParameterOnes(tempConditionID) := tempACUParameterOnes(activeCUIndex);
3736 engACParameterTwos(tempConditionID) := tempACUParameterTwos(activeCUIndex);
3737 engACParameterThrees(tempConditionID) := tempACUParameterThrees(activeCUIndex);
3738 engACIncludeLowerLimits(tempConditionID) := tempACUIncludeLowerLimits(activeCUIndex);
3739 engACIncludeUpperLimits(tempConditionID) := tempACUIncludeUpperLimits(activeCUIndex);
3740 end if;
3741 /*
3742 If this iteration starts an item class, record this iteration's index
3743 in engACUsageFirstIndexes.
3744 */
3745 if(activeCUIndex = 1 or
3746 tempItemClassID <> tempACUItemClassIds(activeCUIndex - 1)) then
3747 engACUsageFirstIndexes(tempItemClassID) := activeCUIndex;
3748 end if;
3749 /*
3750 If this iteration is the last iteration for its item class,
3751 record the item class' active-condition-usage count.
3752 */
3753 if(activeCUIndex = tempCount or
3754 tempItemClassID <> tempACUItemClassIds(activeCUIndex + 1)) then
3755 engACUsageItemClassCounts(tempItemClassID) :=
3756 activeCUIndex - engACUsageFirstIndexes(tempItemClassID) + 1;
3757 end if;
3758 /*
3759 Write the rule priority and rule type into engACUsageRulePriorities indexed by rule ID.
3760 This lets the engine fetch the rule priorities and types efficiently, without carrying
3761 them through all of its algorithms.
3762 */
3763 tempRuleId := engACUsageRuleIds(activeCUIndex);
3764 engACUsageRulePriorities(tempRuleId) := tempACURulePriorities(activeCUIndex);
3765 engACUsageRuleTypes(tempRuleId) := tempACURuleTypes(activeCUIndex);
3766 engACUsageRuleApprCategories(tempRuleId) := tempACURuleApprCats(activeCUIndex);
3767 end loop;
3768 /* Second, fetch the string values for any active conditions on string attributes. */
3769 open activeCondStringValueCursor;
3770 fetch activeCondStringValueCursor bulk collect
3771 into
3772 tempACConditionIds,
3773 engACStringValues;
3774 close activeCondStringValueCursor;
3775 /* Loop through the string conditions, writing them out to the engACStringValue variables. */
3776 tempCount := tempACConditionIds.count;
3777 for stringValueIndex in 1 .. tempCount loop
3778 tempConditionID := tempACConditionIds(stringValueIndex);
3779 /*
3780 If this iteration starts a condition's string-value list, record this
3781 iteration's index in engACStringValueFirstIndexes.
3782 */
3783 if(stringValueIndex = 1 or
3784 tempConditionID <> tempACConditionIds(stringValueIndex - 1)) then
3785 engACStringValueFirstIndexes(tempConditionID) := stringValueIndex;
3786 end if;
3787 /*
3788 engACStringValueCounts(condition_id) is the number of rows in
3789 engACStringValues for the condition with ID condition_id, starting at
3790 the index engACStringValueFirstIndexes(condition_id).
3791 */
3792 if(stringValueIndex = tempCount or
3793 tempConditionID <> tempACConditionIds(stringValueIndex + 1)) then
3794 engACStringValueCounts(tempConditionID) :=
3795 stringValueIndex - engACStringValueFirstIndexes(tempConditionID) + 1;
3796 end if;
3797 end loop;
3798 exception
3799 when others then
3800 if(activeCondUsageCursor%isopen) then
3801 close activeCondUsageCursor;
3802 end if;
3803 if(activeCondStringValueCursor%isopen) then
3804 close activeCondStringValueCursor;
3805 end if;
3806 ame_util.runtimeException(packageNameIn => 'ame_engine',
3807 routineNameIn => 'fetchActiveConditionUsages',
3808 exceptionNumberIn => sqlcode,
3809 exceptionStringIn => sqlerrm);
3810 raise;
3811 end fetchActiveConditionUsages;
3812 procedure fetchApplicableActions as
3813 cursor applicableActionsCursor(ruleIdIn in integer) is
3814 select
3815 ame_actions.action_type_id,
3816 ame_actions.parameter,
3817 ame_actions.parameter_two
3818 from
3819 ame_actions,
3820 ame_action_usages
3821 where
3822 ame_actions.action_id = ame_action_usages.action_id and
3823 ame_action_usages.rule_id = ruleIdIn and
3824 engEffectiveRuleDate between
3825 ame_actions.start_date and
3826 nvl(ame_actions.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3827 engEffectiveRuleDate between
3828 ame_action_usages.start_date and
3829 nvl(ame_action_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate);
3830 productionActionTypeId integer;
3831 tempActionTypeIds ame_util.idList;
3832 tempBoolean boolean;
3833 tempNewRuleIndex integer;
3834 tempRuleCount integer;
3835 tempRuleIndex integer;
3836 tempParameters ame_util.stringList;
3837 tempParameterTwos ame_util.stringList;
3838 tempPerAppProdIndex integer;
3839 begin
3840 /* Initialize per-approver-production variables. */
3841 productionActionTypeId := getActionTypeId(actionTypeNameIn => ame_util.productionActionTypeName);
3842 tempPerAppProdIndex := 0; /* pre-increment */
3843 /* Delete priorities, to make sure they don't get used from here on. */
3844 engAppPriorities.delete;
3845 /* Fetch each applicable rule's actions. */
3846 tempRuleCount := engAppRuleIds.count;
3847 tempNewRuleIndex := tempRuleCount; /* pre-increment tempNewRuleIndex */
3848 for i in 1 .. tempRuleCount loop
3849 tempActionTypeIds.delete;
3850 tempParameters.delete;
3851 tempParameterTwos.delete;
3852 open applicableActionsCursor(ruleIdIn => engAppRuleIds(i));
3853 fetch applicableActionsCursor bulk collect
3854 into
3855 tempActionTypeIds,
3856 tempParameters,
3857 tempParameterTwos;
3858 close applicableActionsCursor;
3859 /* Populate the engAppPerAppProd variables. */
3860 if(engAppRuleTypes(i) <> ame_util.productionRuleType) then
3861 tempBoolean := true; /* Here tempBoolean is true until a production action for this rule is found. */
3862 for j in 1 .. tempActionTypeIds.count loop
3863 if(engActionTypeUsages(tempActionTypeIds(j)) = ame_util.productionRuleType) then
3864 tempPerAppProdIndex := tempPerAppProdIndex + 1;
3865 if(tempBoolean) then
3866 tempBoolean := false;
3867 engAppPerAppProdFirstIndexes(engAppRuleIds(i)) := tempPerAppProdIndex;
3868 end if;
3869 engAppPerAppProdRuleIds(tempPerAppProdIndex) := engAppRuleIds(i);
3870 engAppPerAppProdVariableNames(tempPerAppProdIndex) := tempParameters(j);
3871 engAppPerAppProdVariableValues(tempPerAppProdIndex) := tempParameterTwos(j);
3872 tempActionTypeIds(j) := null; /* This prevents further processing later. */
3873 end if;
3874 end loop;
3875 end if;
3876 /*
3877 If the rule is a production rule, put the first action in the same row as the rule.
3878 Otherwise, put the first non-production action in that row. (There should always be
3879 at least one non-production action in a non-production rule, and at least one production
3880 action in a production rule.) Put any remaining actions (non-production actions, unless
3881 the rule is a production rule) in new rows.
3882 */
3883 /* Here tempBoolean is true until the first useable production action is found. */
3884 tempBoolean := true;
3885 for j in 1 .. tempActionTypeIds.count loop
3886 /* Ignore actions with null action-type IDs; these were per-approver production actions. */
3887 if(tempActionTypeIds(j) is not null) then
3888 if(tempBoolean) then
3889 tempBoolean := false;
3890 tempRuleIndex := i;
3891 else
3892 tempNewRuleIndex := tempNewRuleIndex + 1;
3893 tempRuleIndex := tempNewRuleIndex;
3894 end if;
3895 engAppItemClassIds(tempRuleIndex) := engAppItemClassIds(i);
3896 engAppItemIds(tempRuleIndex) := engAppItemIds(i);
3897 engAppRuleIds(tempRuleIndex) := engAppRuleIds(i);
3898 engRuleAppliedYN(tempRuleIndex) := engRuleAppliedYN(i);
3899 engAppRuleTypes(tempRuleIndex) := engAppRuleTypes(i);
3900 engAppApproverCategories(tempRuleIndex) := engAppApproverCategories(i);
3901 engAppActionTypeIds(tempRuleIndex) := tempActionTypeIds(j);
3902 engAppParameters(tempRuleIndex) := tempParameters(j);
3903 engAppParameterTwos(tempRuleIndex) := tempParameterTwos(j);
3904 engAppRuleItemClassIds(tempRuleIndex) := engAppRuleItemClassIds(i);
3905 engAppAppItemIds(tempRuleIndex) := engAppAppItemIds(i);
3906 end if;
3907 end loop;
3908 end loop;
3909 /* Convert combination rules to other rule types. */
3910 for i in 1 .. engAppRuleTypes.count loop
3911 if(engAppRuleTypes(i) = ame_util.combinationRuleType) then
3912 engAppRuleTypes(i) := engActionTypeUsages(engAppActionTypeIds(i));
3913 /* The following if statement was added to resolve bug 3522880. */
3914 if(engAppRuleTypes(i) in (ame_util.listModRuleType, ame_util.substitutionRuleType)) then
3915 engAppLMSubItemClassIds(engAppRuleIds(i)) := engAppRuleItemClassIds(i);
3916 engAppLMSubItemIds(engAppRuleIds(i)) := engAppAppItemIds(i);
3917 engAppRuleItemClassIds(i) := null;
3918 engAppAppItemIds(i) := null;
3919 end if;
3920 end if;
3921 end loop;
3922 /*
3923 Sort all of the engApp lists: first by item-class order number, then by
3924 item-class ID, then by item ID, then by rule type, then by action-type order
3925 number, then by action-type ID. See engApp declaration comment block for
3926 details.
3927 */
3928 sortApplicableRules(sortByActionTypeIn => true);
3929 /* Restore the item-class IDs and item IDs of list-modification and substitution rules. */
3930 for i in 1 .. engAppRuleIds.count loop
3931 /* The following if statement was changed to resolve bug 3522880. */
3932 -- if(engAppRuleTypes(i) in (ame_util.listModRuleType, ame_util.substitutionRuleType)) then
3933 if(engAppRuleItemClassIds(i) is null) then
3934 engAppRuleItemClassIds(i) := engAppLMSubItemClassIds(engAppRuleIds(i));
3935 engAppAppItemIds(i) := engAppLMSubItemIds(engAppRuleIds(i));
3936 engRuleAppliedYN(i) := ame_util.booleanFalse;
3937 end if;
3938 end loop;
3939 engAppLMSubItemClassIds.delete;
3940 engAppLMSubItemIds.delete;
3941 exception
3942 when others then
3943 if(applicableActionsCursor%isopen) then
3944 close applicableActionsCursor;
3945 end if;
3946 ame_util.runtimeException(packageNameIn => 'ame_engine',
3947 routineNameIn => 'fetchApplicableActions',
3948 exceptionNumberIn => sqlcode,
3949 exceptionStringIn => sqlerrm);
3950 raise;
3951 end fetchApplicableActions;
3952 procedure fetchAttributeValues(fetchInactivesIn in boolean) as
3953 cursor attributeCursor(applicationIdIn in integer,
3954 fetchInactivesIn in varchar2) is
3955 select
3956 ame_attributes.attribute_id attribute_id,
3957 ame_attributes.name attribute_name,
3958 ame_attributes.attribute_type attribute_type,
3959 ame_attributes.item_class_id item_class_id,
3960 ame_attribute_usages.query_string,
3961 ame_attribute_usages.is_static
3962 from
3963 ame_attributes,
3964 ame_attribute_usages,
3965 ame_item_class_usages
3966 where
3967 ame_attributes.name not in (ame_util.workflowItemKeyAttribute, ame_util.workflowItemTypeAttribute) and
3968 ame_attributes.attribute_id = ame_attribute_usages.attribute_id and
3969 ame_attribute_usages.application_id = applicationIdIn and
3970 ame_item_class_usages.application_id = applicationIdIn and
3971 ame_attributes.item_class_id = ame_item_class_usages.item_class_id and
3972 (fetchInactivesIn = ame_util.booleanTrue or
3973 ame_attribute_usages.use_count > 0 or
3974 ame_attributes.attribute_id in
3975 (select ame_attributes2.attribute_id
3976 from
3977 ame_attributes ame_attributes2,
3978 ame_mandatory_attributes
3979 where
3980 ame_attributes2.attribute_id = ame_mandatory_attributes.attribute_id and
3981 ame_mandatory_attributes.action_type_id = -1 and
3982 engEffectiveRuleDate between
3983 ame_attributes2.start_date and
3984 nvl(ame_attributes2.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3985 engEffectiveRuleDate between
3986 ame_mandatory_attributes.start_date and
3987 nvl(ame_mandatory_attributes.end_date - ame_util.oneSecond, engEffectiveRuleDate))) and
3988 engEffectiveRuleDate between
3989 ame_attributes.start_date and
3990 nvl(ame_attributes.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3991 engEffectiveRuleDate between
3992 ame_attribute_usages.start_date and
3993 nvl(ame_attribute_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
3994 engEffectiveRuleDate between
3995 ame_item_class_usages.start_date and
3996 nvl(ame_item_class_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate)
3997 /*
3998 The order-by conditions are all necessary. The second is to break
3999 item_class_order_number ties in a determinate order. The third is
4000 to display attribute names in alphabetical order on the test tab.
4001 Compare the itemClassUsageCursor cursor in the procedure updateTransactionState.
4002 */
4003 order by
4004 ame_item_class_usages.item_class_order_number,
4005 ame_item_class_usages.item_class_id,
4006 ame_attributes.name;
4007 cursor testTransCurrencyCursor(attributeIdIn in integer) is
4008 select
4009 attribute_value_1,
4010 attribute_value_2,
4011 attribute_value_3
4012 from ame_test_trans_att_values
4013 where
4014 application_id = engAmeApplicationId and
4015 transaction_id = engTransactionId and
4016 attribute_id = attributeIdIn
4017 order by item_id;
4018 cursor testTransNonCurrencyCursor(attributeIdIn in integer) is
4019 select attribute_value_1
4020 from ame_test_trans_att_values
4021 where
4022 application_id = engAmeApplicationId and
4023 transaction_id = engTransactionId and
4024 attribute_id = attributeIdIn
4025 order by item_id;
4026 cursor testTransVariantHeaderCursor(attributeIdIn in integer) is
4027 select attribute_value_1
4028 from ame_test_trans_att_values
4029 where
4030 application_id = engAmeApplicationId and
4031 transaction_id = engTransactionId and
4032 attribute_id = attributeIdIn and
4033 item_class_id = getItemClassId(ame_util.headerItemClassName) and
4034 item_id = engTransactionId;
4035 attributeCount integer;
4036 attributeIds ame_util.idList;
4037 attributeItemClassIds ame_util.idList;
4038 attributeNames ame_util.stringList;
4039 attributeTypes ame_util.stringList;
4040 dynamicCursor integer;
4041 dynamicQuery ame_util.longestStringType;
4042 errorCode integer;
4043 errorMessage ame_util.longestStringType;
4044 fetchInactives varchar2(1);
4045 isStatics ame_util.charList;
4046 queryStrings ame_util.longestStringList;
4047 rowCountException exception;
4048 rowsFound integer;
4049 tempAttributeId integer;
4050 tempAttributeName ame_attributes.name%type;
4051 tempAttributeType ame_attributes.attribute_type%type;
4052 tempAttributeValue1 ame_util.attributeValueType;
4053 tempAttributeValue2 ame_util.attributeValueType;
4054 tempAttributeValue3 ame_util.attributeValueType;
4055 tempAttributeValueIndex integer;
4056 tempAttributeValues1 dbms_sql.varchar2_table;
4057 tempAttributeValues2 dbms_sql.varchar2_table;
4058 tempAttributeValues3 dbms_sql.varchar2_table;
4059 tempItemClassIndex integer;
4060 begin
4061 /*
4062 fetchInactives is necessary because we can't use a PL/SQL boolean variable
4063 in a select statement.
4064 */
4065 if(fetchInactivesIn) then
4066 fetchInactives := ame_util.booleanTrue;
4067 else
4068 fetchInactives := ame_util.booleanFalse;
4069 end if;
4070 /* Bulk fetch attributeCursor into a PL/SQL table. */
4071 open attributeCursor(applicationIdIn => engAmeApplicationId,
4072 fetchInactivesIn => fetchInactives);
4073 fetch attributeCursor bulk collect
4074 into
4075 attributeIds,
4076 attributeNames,
4077 attributeTypes,
4078 attributeItemClassIds,
4079 queryStrings,
4080 isStatics;
4081 close attributeCursor;
4082 /*
4083 Fetch each attribute's value. The attributes are in order of their item classes'
4084 item_class_order_numbers, so we can simply load them into the attribute package
4085 variables in index order, noting in engAttributeValueIndexes where each attribute's
4086 values start.
4087 */
4088 attributeCount := attributeIds.count;
4089 /* tempAttributeValueIndex indexes into engAttributeValues1-3. Pre-increment it. */
4090 tempAttributeValueIndex := 0;
4091 for i in 1 .. attributeCount loop
4092 tempItemClassIndex := engItemClassIndexes(attributeItemClassIds(i));
4093 tempAttributeId := attributeIds(i);
4094 tempAttributeType := attributeTypes(i);
4095 /* Set the attribute's package variables, even if the attribute's item class has no items. */
4096 engAttributeIsStatics(tempAttributeId) := isStatics(i);
4097 engAttributeNames(tempAttributeId) := attributeNames(i);
4098 engAttributeTypes(tempAttributeId) := attributeTypes(i);
4099 engAttributeItemClassIds(tempAttributeId) := attributeItemClassIds(i);
4100 /* Check if the attribute is a variant and set the engAttributeQueries and engAttributeVariant accordingly */
4101 dynamicQuery := ame_util.removeReturns(stringIn => queryStrings(i),
4102 replaceWithSpaces => true);
4103 if(checkAttributeVariant(attributeIdIn => tempAttributeId) = ame_util.booleanTrue) then
4104 if ((isStatics(i) = ame_util.booleanFalse) and
4105 (instrb(dynamicQuery, ame_util2.itemClassPlaceHolder) > 0 or
4106 instrb(dynamicQuery, ame_util2.itemIdPlaceHolder) > 0)) then
4107 engAttributeVariant(tempAttributeId) := ame_util.booleanTrue;
4108 engAttributeQueries(tempAttributeId) := queryStrings(i);
4109 end if;
4110 end if;
4111 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4112 fnd_log.string
4113 (fnd_log.level_statement
4114 ,'ame_engine.fetchAttributeValues'
4115 ,'Attribute ::: ' || engAttributeNames(tempAttributeId) || '(' || tempAttributeId || ')'
4116 );
4117 end if;
4118 /*
4119 Set this attribute's values in engAttributeValues1-3, if the attribute's item class
4120 has any items.
4121 */
4122 if(engItemCounts(tempItemClassIndex) = 0) then
4123 engAttributeValueIndexes(attributeIds(i)) := null;
4124 else
4125 /* (tempAttributeValueIndex will be pre-incremented when it's actually used.) */
4126 engAttributeValueIndexes(attributeIds(i)) := tempAttributeValueIndex + 1;
4127 if(engIsTestTransaction) then
4128 tempAttributeValues1.delete;
4129 tempAttributeValues2.delete;
4130 tempAttributeValues3.delete;
4131 if(checkAttributeVariant(tempAttributeId) = ame_util.booleanTrue) then
4132 open testTransVariantHeaderCursor(attributeIdIn => tempAttributeId);
4133 fetch testTransVariantHeaderCursor bulk collect
4134 into tempAttributeValues1;
4135 close testTransVariantHeaderCursor;
4136 else
4137 if(tempAttributeType = ame_util.currencyAttributeType) then
4138 open testTransCurrencyCursor(attributeIdIn => tempAttributeId);
4139 fetch testTransCurrencyCursor bulk collect
4140 into
4141 tempAttributeValues1,
4142 tempAttributeValues2,
4143 tempAttributeValues3;
4144 close testTransCurrencyCursor;
4145 else
4146 open testTransNonCurrencyCursor(attributeIdIn => tempAttributeId);
4147 fetch testTransNonCurrencyCursor bulk collect
4148 into tempAttributeValues1;
4149 close testTransNonCurrencyCursor;
4150 end if;
4151 end if;
4152 for j in 1 .. tempAttributeValues1.count loop
4153 tempAttributeValueIndex := tempAttributeValueIndex + 1;
4154 engAttributeValues1(tempAttributeValueIndex) := tempAttributeValues1(j);
4155 if(tempAttributeType = ame_util.currencyAttributeType) then
4156 engAttributeValues2(tempAttributeValueIndex) := tempAttributeValues2(j);
4157 engAttributeValues3(tempAttributeValueIndex) := tempAttributeValues3(j);
4158 else
4159 engAttributeValues2(tempAttributeValueIndex) := null;
4160 engAttributeValues3(tempAttributeValueIndex) := null;
4161 end if;
4162 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4163 fnd_log.string
4164 (fnd_log.level_statement
4165 ,'ame_engine.fetchAttributeValues'
4166 ,'Attribute Value :' || engAttributeValues1(tempAttributeValueIndex) ||
4167 ':' || engAttributeValues2(tempAttributeValueIndex) || ':' || engAttributeValues3(tempAttributeValueIndex) || ':'
4168 );
4169 end if;
4170 end loop;
4171 if tempAttributeValues1.count = 0 then
4172 for j in 1 .. engItemCounts(tempItemClassIndex) loop
4173 tempAttributeValueIndex := tempAttributeValueIndex + 1;
4174 engAttributeValues1(tempAttributeValueIndex) := null;
4175 engAttributeValues2(tempAttributeValueIndex) := null;
4176 engAttributeValues3(tempAttributeValueIndex) := null;
4177 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4178 fnd_log.string
4179 (fnd_log.level_statement
4180 ,'ame_engine.fetchAttributeValues'
4181 ,'Attribute Value :' || engAttributeValues1(tempAttributeValueIndex) ||
4182 ':' || engAttributeValues2(tempAttributeValueIndex) || ':' || engAttributeValues3(tempAttributeValueIndex) || ':'
4183 );
4184 end if;
4185 end loop;
4186 end if;
4187 else
4188 if(isStatics(i) = ame_util.booleanTrue) then
4189 /*
4190 Write the static usage into the attribute-value package variables once for each item
4191 of the attribute's item class.
4192 */
4193 if(attributeTypes(i) = ame_util.currencyAttributeType) then
4194 ame_util.parseStaticCurAttValue(applicationIdIn => engAmeApplicationId,
4195 attributeIdIn => tempAttributeId,
4196 attributeValueIn => queryStrings(i),
4197 localErrorIn => false,
4198 amountOut => tempAttributeValue1,
4199 currencyOut => tempAttributeValue2,
4200 conversionTypeOut => tempAttributeValue3);
4201 else
4202 tempAttributeValue1 := queryStrings(i);
4203 tempAttributeValue2 := null;
4204 tempAttributeValue3 := null;
4205 end if;
4206 for j in 1 .. engItemCounts(tempItemClassIndex) loop
4207 tempAttributeValueIndex := tempAttributeValueIndex + 1;
4208 engAttributeValues1(tempAttributeValueIndex) := tempAttributeValue1;
4209 engAttributeValues2(tempAttributeValueIndex) := tempAttributeValue2;
4210 engAttributeValues3(tempAttributeValueIndex) := tempAttributeValue3;
4211 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4212 fnd_log.string
4213 (fnd_log.level_statement
4214 ,'ame_engine.fetchAttributeValues'
4215 ,'Attribute Value :' || engAttributeValues1(tempAttributeValueIndex) ||
4216 ':' || engAttributeValues2(tempAttributeValueIndex) || ':' || engAttributeValues3(tempAttributeValueIndex) || ':'
4217 );
4218 end if;
4219 end loop;
4220 else
4221 tempAttributeValues1.delete;
4222 tempAttributeValues2.delete;
4223 tempAttributeValues3.delete;
4224 /*
4225 We need to do old-style dynamic PL/SQL here to make sure all occurrences of
4226 ame_util.transactionIdPlaceholder in dynamicQuery get bound.
4227 */
4228 dynamicQuery := ame_util.removeReturns(stringIn => queryStrings(i),
4229 replaceWithSpaces => true);
4230 dynamicCursor := dbms_sql.open_cursor;
4231 dbms_sql.parse(dynamicCursor,
4232 dynamicQuery,
4233 dbms_sql.native);
4234 if(instrb(dynamicQuery, ame_util.transactionIdPlaceholder) > 0) then
4235 dbms_sql.bind_variable(dynamicCursor,
4236 ame_util.transactionIdPlaceholder,
4237 engTransactionId,
4238 50); /* ame_temp_transactions.transaction_id%length doesn't work here. */
4239 end if;
4240 if(instrb(dynamicQuery, ame_util2.itemClassPlaceHolder) > 0) then
4241 dbms_sql.bind_variable(dynamicCursor,
4242 ame_util2.itemClassPlaceHolder,
4243 ame_util.headerItemClassName,
4244 50); /* ame_temp_transactions.transaction_id%length doesn't work here. */
4245 end if;
4246 if(instrb(dynamicQuery, ame_util2.itemIdPlaceHolder) > 0) then
4247 dbms_sql.bind_variable(dynamicCursor,
4248 ame_util2.itemIdPlaceHolder,
4249 engTransactionId,
4250 50); /* ame_temp_transactions.transaction_id%length doesn't work here. */
4251 end if;
4252 dbms_sql.define_array(dynamicCursor,
4253 1,
4254 tempAttributeValues1,
4255 ame_util.attributeValueTypeLength,
4256 1);
4257 if(tempAttributeType = ame_util.currencyAttributeType) then
4258 dbms_sql.define_array(dynamicCursor,
4259 2,
4260 tempAttributeValues2,
4261 ame_util.attributeValueTypeLength,
4262 1);
4263 dbms_sql.define_array(dynamicCursor,
4264 3,
4265 tempAttributeValues3,
4266 ame_util.attributeValueTypeLength,
4267 1);
4268 end if;
4269 rowsFound := dbms_sql.execute(dynamicCursor);
4270 loop
4271 rowsFound := dbms_sql.fetch_rows(dynamicCursor);
4272 dbms_sql.column_value(dynamicCursor,
4273 1,
4274 tempAttributeValues1);
4275 if(tempAttributeType = ame_util.currencyAttributeType) then
4276 dbms_sql.column_value(dynamicCursor,
4277 2,
4278 tempAttributeValues2);
4279 dbms_sql.column_value(dynamicCursor,
4280 3,
4281 tempAttributeValues3);
4282 end if;
4283 exit when rowsFound < 100;
4284 end loop;
4285 dbms_sql.close_cursor(dynamicCursor);
4286 /* Make sure the attribute usage returned the right number of rows. */
4287 if(tempAttributeValues1.count <> engItemCounts(tempItemClassIndex)) then
4288 raise rowCountException;
4289 end if;
4290 /* Transfer the attribute values into the appropriate package variables. */
4291 for j in 1 .. tempAttributeValues1.count loop
4292 tempAttributeValueIndex := tempAttributeValueIndex + 1;
4293 engAttributeValues1(tempAttributeValueIndex) := tempAttributeValues1(j);
4294 if(tempAttributeType = ame_util.currencyAttributeType) then
4295 engAttributeValues2(tempAttributeValueIndex) := tempAttributeValues2(j);
4296 engAttributeValues3(tempAttributeValueIndex) := tempAttributeValues3(j);
4297 else
4298 engAttributeValues2(tempAttributeValueIndex) := null;
4299 engAttributeValues3(tempAttributeValueIndex) := null;
4300 end if;
4301 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4302 fnd_log.string
4303 (fnd_log.level_statement
4304 ,'ame_engine.fetchAttributeValues'
4305 ,'Attribute Value :' || engAttributeValues1(tempAttributeValueIndex) ||
4306 ':' || engAttributeValues2(tempAttributeValueIndex) || ':' || engAttributeValues3(tempAttributeValueIndex) || ':'
4307 );
4308 end if;
4309 end loop;
4310 end if;
4311 end if;
4312 end if;
4313 end loop;
4314 exception
4315 when rowCountException then
4316 if(attributeCursor%isopen) then
4317 close attributeCursor;
4318 end if;
4319 if(dbms_sql.is_open(dynamicCursor)) then
4320 dbms_sql.close_cursor(dynamicCursor);
4321 end if;
4322 if(testTransCurrencyCursor%isopen) then
4323 close testTransCurrencyCursor;
4324 end if;
4325 if(testTransNonCurrencyCursor%isopen) then
4326 close testTransNonCurrencyCursor;
4327 end if;
4328 tempAttributeName := ame_attribute_pkg.getName(attributeIdIn => tempAttributeId);
4329 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4330 fnd_log.string
4331 (fnd_log.level_statement
4332 ,'ame_engine.fetchAttributeValues'
4333 ,'Attribute ::: ' || tempAttributeName || '(' || tempAttributeId || ')'||
4334 'attribute returned ::'||tempAttributeValues1.count||'rows but the number of items for the '||
4335 'itemclass ::'||engItemCounts(tempItemClassIndex)
4336 );
4337 end if;
4338 errorCode := -20108;
4339 errorMessage :=
4340 ame_util.getMessage(applicationShortNameIn =>'PER',
4341 messageNameIn => 'AME_400684_ATR_INV_DYN_USG',
4342 tokenNameOneIn => 'ATTRIBUTE_NAME',
4343 tokenValueOneIn => tempAttributeName);
4344 ame_util.runtimeException(packageNameIn => 'ame_engine',
4345 routineNameIn => 'fetchAttributeValues',
4346 exceptionNumberIn => errorCode,
4347 exceptionStringIn => errorMessage);
4348 raise_application_error(errorCode,
4349 errorMessage);
4350 when others then
4351 if(attributeCursor%isopen) then
4352 close attributeCursor;
4353 end if;
4354 if(dbms_sql.is_open(dynamicCursor)) then
4355 dbms_sql.close_cursor(dynamicCursor);
4356 end if;
4357 if(testTransCurrencyCursor%isopen) then
4358 close testTransCurrencyCursor;
4359 end if;
4360 if(testTransNonCurrencyCursor%isopen) then
4361 close testTransNonCurrencyCursor;
4362 end if;
4363 tempAttributeName := ame_attribute_pkg.getName(attributeIdIn => tempAttributeId);
4364 errorMessage := sqlerrm;
4365 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4366 fnd_log.string
4367 (fnd_log.level_statement
4368 ,'ame_engine.fetchAttributeValues'
4369 ,'Attribute ::: ' || tempAttributeName || '(' || tempAttributeId || '),error:'||errorMessage
4370 );
4371 end if;
4372 ame_util.runtimeException(packageNameIn => 'ame_engine',
4373 routineNameIn => 'fetchAttributeValues',
4374 exceptionNumberIn => sqlcode,
4375 exceptionStringIn => errorMessage);
4376 raise;
4377 end fetchAttributeValues;
4378 procedure fetchOtherAttributeValues as
4379 cursor attributeCursor(applicationIdIn in integer) is
4380 select
4381 ame_attributes.attribute_id attribute_id,
4382 ame_attributes.name attribute_name,
4383 ame_attributes.attribute_type attribute_type,
4384 ame_attributes.item_class_id item_class_id,
4385 ame_attribute_usages.query_string,
4386 ame_attribute_usages.is_static
4387 from
4388 ame_attributes,
4389 ame_attribute_usages,
4390 ame_item_class_usages
4391 where
4392 ame_attributes.name not in (ame_util.workflowItemKeyAttribute, ame_util.workflowItemTypeAttribute) and
4393 ame_attributes.attribute_id = ame_attribute_usages.attribute_id and
4394 ame_attribute_usages.application_id = applicationIdIn and
4395 ame_item_class_usages.application_id = applicationIdIn and
4396 ame_attributes.item_class_id = ame_item_class_usages.item_class_id and
4397 (ame_attribute_usages.use_count = 0 and
4398 ame_attributes.attribute_id not in
4399 (select ame_attributes2.attribute_id
4400 from
4401 ame_attributes ame_attributes2,
4402 ame_mandatory_attributes
4403 where
4404 ame_attributes2.attribute_id = ame_mandatory_attributes.attribute_id and
4405 ame_mandatory_attributes.action_type_id = -1 and
4406 sysdate between
4407 ame_attributes2.start_date and
4408 nvl(ame_attributes2.end_date - ame_util.oneSecond, sysdate) and
4409 sysdate between
4410 ame_mandatory_attributes.start_date and
4411 nvl(ame_mandatory_attributes.end_date - ame_util.oneSecond, sysdate))) and
4412 sysdate between
4413 ame_attributes.start_date and
4414 nvl(ame_attributes.end_date - ame_util.oneSecond, sysdate) and
4415 sysdate between
4416 ame_attribute_usages.start_date and
4417 nvl(ame_attribute_usages.end_date - ame_util.oneSecond, sysdate) and
4418 sysdate between
4419 ame_item_class_usages.start_date and
4420 nvl(ame_item_class_usages.end_date - ame_util.oneSecond, sysdate) and
4421 -- Condition to check whether the attribute is used in the rule
4422 exists
4423 (
4424 select 1
4425 from ame_conditions,
4426 ame_condition_usages,
4427 ame_rules,
4428 ame_rule_usages
4429 where ame_conditions.attribute_id = ame_attributes.attribute_id
4430 and ame_conditions.condition_id = ame_condition_usages.condition_id
4431 and ame_condition_usages.rule_id = ame_rules.rule_id
4432 and ame_rules.rule_id = ame_rule_usages.rule_id
4433 and ame_rule_usages.item_id = applicationIdIn
4434 and ((engEffectiveRuleDate between ame_rules.start_date
4435 and nvl(ame_rules.end_date - (1/86400), engEffectiveRuleDate)))
4436 and ((engEffectiveRuleDate between ame_rule_usages.start_date
4437 and nvl(ame_rule_usages.end_date - (1/86400), engEffectiveRuleDate)))
4438 and engEffectiveRuleDate between ame_conditions.start_date
4439 and nvl(ame_conditions.end_date - (1/86400), engEffectiveRuleDate)
4440 and ((engEffectiveRuleDate between ame_condition_usages.start_date
4441 and nvl(ame_condition_usages.end_date - (1/86400), engEffectiveRuleDate)))
4442 union
4443 select 1
4444 from ame_mandatory_attributes,
4445 ame_actions,
4446 ame_action_usages,
4447 ame_rules,
4448 ame_rule_usages
4449 where ame_mandatory_attributes.attribute_id = ame_attributes.attribute_id
4450 and ame_mandatory_attributes.action_type_id =
4451 ame_actions.action_type_id
4452 and ame_actions.action_id = ame_action_usages.action_id
4453 and ame_action_usages.rule_id = ame_rules.rule_id
4454 and ame_rules.rule_id = ame_rule_usages.rule_id
4455 and ame_rule_usages.item_id = applicationIdIn
4456 and ((engEffectiveRuleDate between ame_rules.start_date
4457 and nvl(ame_rules.end_date - (1/86400), engEffectiveRuleDate)))
4458 and ((engEffectiveRuleDate between ame_rule_usages.start_date
4459 and nvl(ame_rule_usages.end_date - (1/86400), engEffectiveRuleDate)))
4460 and engEffectiveRuleDate between ame_mandatory_attributes.start_date
4461 and nvl(ame_mandatory_attributes.end_date - (1/86400), engEffectiveRuleDate)
4462 and engEffectiveRuleDate between ame_actions.start_date
4463 and nvl(ame_actions.end_date - (1/86400), engEffectiveRuleDate)
4464 and ((engEffectiveRuleDate between ame_action_usages.start_date
4465 and nvl(ame_action_usages.end_date - (1/86400), engEffectiveRuleDate)))
4466 )
4467 /*
4468 The order-by conditions are all necessary. The second is to break
4469 item_class_order_number ties in a determinate order. The third is
4470 to display attribute names in alphabetical order on the test tab.
4471 Compare the itemClassUsageCursor cursor in the procedure updateTransactionState.
4472 */
4473 order by
4474 ame_item_class_usages.item_class_order_number,
4475 ame_item_class_usages.item_class_id,
4476 ame_attributes.name;
4477 cursor testTransCurrencyCursor(attributeIdIn in integer) is
4478 select
4479 attribute_value_1,
4480 attribute_value_2,
4481 attribute_value_3
4482 from ame_test_trans_att_values
4483 where
4484 application_id = engAmeApplicationId and
4485 transaction_id = engTransactionId and
4486 attribute_id = attributeIdIn
4487 order by item_id;
4488 cursor testTransNonCurrencyCursor(attributeIdIn in integer) is
4489 select attribute_value_1
4490 from ame_test_trans_att_values
4491 where
4492 application_id = engAmeApplicationId and
4493 transaction_id = engTransactionId and
4494 attribute_id = attributeIdIn
4495 order by item_id;
4496 cursor testTransVariantHeaderCursor(attributeIdIn in integer) is
4497 select attribute_value_1
4498 from ame_test_trans_att_values
4499 where
4500 application_id = engAmeApplicationId and
4501 transaction_id = engTransactionId and
4502 attribute_id = attributeIdIn and
4503 item_class_id = getItemClassId(ame_util.headerItemClassName) and
4504 item_id = engTransactionId;
4505 attributeCount integer;
4506 attributeIds ame_util.idList;
4507 attributeItemClassIds ame_util.idList;
4508 attributeNames ame_util.stringList;
4509 attributeTypes ame_util.stringList;
4510 dynamicCursor integer;
4511 dynamicQuery ame_util.longestStringType;
4512 errorCode integer;
4513 errorMessage ame_util.longestStringType;
4514 fetchInactives varchar2(1);
4515 isStatics ame_util.charList;
4516 queryStrings ame_util.longestStringList;
4517 rowCountException exception;
4518 rowsFound integer;
4519 tempAttributeId integer;
4520 tempAttributeName ame_attributes.name%type;
4521 tempAttributeType ame_attributes.attribute_type%type;
4522 tempAttributeValue1 ame_util.attributeValueType;
4523 tempAttributeValue2 ame_util.attributeValueType;
4524 tempAttributeValue3 ame_util.attributeValueType;
4525 tempAttributeValueIndex integer;
4526 tempAttributeValues1 dbms_sql.varchar2_table;
4527 tempAttributeValues2 dbms_sql.varchar2_table;
4528 tempAttributeValues3 dbms_sql.varchar2_table;
4529 tempItemClassIndex integer;
4530 begin
4531 open attributeCursor(applicationIdIn => engAmeApplicationId);
4532
4533 fetch attributeCursor bulk collect
4534 into
4535 attributeIds,
4536 attributeNames,
4537 attributeTypes,
4538 attributeItemClassIds,
4539 queryStrings,
4540 isStatics;
4541 close attributeCursor;
4542 /*
4543 Fetch each attribute's value. The attributes are in order of their item classes'
4544 item_class_order_numbers, so we can simply load them into the attribute package
4545 variables in index order, noting in engAttributeValueIndexes where each attribute's
4546 values start.
4547 */
4548 attributeCount := attributeIds.count;
4549 /* tempAttributeValueIndex indexes into engAttributeValues1-3. Pre-increment it. */
4550 tempAttributeValueIndex := engAttributeValues1.last;--getMaxValueIndex;
4551 for i in 1 .. attributeCount loop
4552 tempItemClassIndex := engItemClassIndexes(attributeItemClassIds(i));
4553 tempAttributeId := attributeIds(i);
4554 tempAttributeType := attributeTypes(i);
4555 /* Set the attribute's package variables, even if the attribute's item class has no items. */
4556 engAttributeIsStatics(tempAttributeId) := isStatics(i);
4557 engAttributeNames(tempAttributeId) := attributeNames(i);
4558 engAttributeTypes(tempAttributeId) := attributeTypes(i);
4559 engAttributeItemClassIds(tempAttributeId) := attributeItemClassIds(i);
4560 /* Check if the attribute is a variant and set the engAttributeQueries and engAttributeVariant accordingly */
4561 dynamicQuery := ame_util.removeReturns(stringIn => queryStrings(i),
4562 replaceWithSpaces => true);
4563 if(checkAttributeVariant(attributeIdIn => tempAttributeId) = ame_util.booleanTrue) then
4564 if ((isStatics(i) = ame_util.booleanFalse) and
4565 (instrb(dynamicQuery, ame_util2.itemClassPlaceHolder) > 0 or
4566 instrb(dynamicQuery, ame_util2.itemIdPlaceHolder) > 0)) then
4567 engAttributeVariant(tempAttributeId) := ame_util.booleanTrue;
4568 engAttributeQueries(tempAttributeId) := queryStrings(i);
4569 end if;
4570 end if;
4571 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4572 fnd_log.string
4573 (fnd_log.level_statement
4574 ,'ame_engine.fetchOtherAttributeValues'
4575 ,'Attribute ::: ' || engAttributeNames(tempAttributeId) || '(' || tempAttributeId || ')'
4576 );
4577 end if;
4578 /*
4579 Set this attribute's values in engAttributeValues1-3, if the attribute's item class
4580 has any items.
4581 */
4582 if(engItemCounts(tempItemClassIndex) = 0) then
4583 engAttributeValueIndexes(attributeIds(i)) := null;
4584 else
4585 /* (tempAttributeValueIndex will be pre-incremented when it's actually used.) */
4586 engAttributeValueIndexes(attributeIds(i)) := tempAttributeValueIndex + 1;
4587 if(engIsTestTransaction) then
4588 tempAttributeValues1.delete;
4589 tempAttributeValues2.delete;
4590 tempAttributeValues3.delete;
4591 if(checkAttributeVariant(tempAttributeId) = ame_util.booleanTrue) then
4592 open testTransVariantHeaderCursor(attributeIdIn => tempAttributeId);
4593 fetch testTransVariantHeaderCursor bulk collect
4594 into tempAttributeValues1;
4595 close testTransVariantHeaderCursor;
4596 else
4597 if(tempAttributeType = ame_util.currencyAttributeType) then
4598 open testTransCurrencyCursor(attributeIdIn => tempAttributeId);
4599 fetch testTransCurrencyCursor bulk collect
4600 into
4601 tempAttributeValues1,
4602 tempAttributeValues2,
4603 tempAttributeValues3;
4604 close testTransCurrencyCursor;
4605 else
4606 open testTransNonCurrencyCursor(attributeIdIn => tempAttributeId);
4607 fetch testTransNonCurrencyCursor bulk collect
4608 into tempAttributeValues1;
4609 close testTransNonCurrencyCursor;
4610 end if;
4611 end if;
4612 for j in 1 .. tempAttributeValues1.count loop
4613 tempAttributeValueIndex := tempAttributeValueIndex + 1;
4614 engAttributeValues1(tempAttributeValueIndex) := tempAttributeValues1(j);
4615 if(tempAttributeType = ame_util.currencyAttributeType) then
4616 engAttributeValues2(tempAttributeValueIndex) := tempAttributeValues2(j);
4617 engAttributeValues3(tempAttributeValueIndex) := tempAttributeValues3(j);
4618 else
4619 engAttributeValues2(tempAttributeValueIndex) := null;
4620 engAttributeValues3(tempAttributeValueIndex) := null;
4621 end if;
4622 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4623 fnd_log.string
4624 (fnd_log.level_statement
4625 ,'ame_engine.fetchOtherAttributeValues'
4626 ,'Attribute Value :' || engAttributeValues1(tempAttributeValueIndex) ||
4627 ':' || engAttributeValues2(tempAttributeValueIndex) || ':' || engAttributeValues3(tempAttributeValueIndex) || ':'
4628 );
4629 end if;
4630 end loop;
4631 if tempAttributeValues1.count = 0 then
4632 for j in 1 .. engItemCounts(tempItemClassIndex) loop
4633 tempAttributeValueIndex := tempAttributeValueIndex + 1;
4634 engAttributeValues1(tempAttributeValueIndex) := null;
4635 engAttributeValues2(tempAttributeValueIndex) := null;
4636 engAttributeValues3(tempAttributeValueIndex) := null;
4637 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4638 fnd_log.string
4639 (fnd_log.level_statement
4640 ,'ame_engine.fetchOtherAttributeValues'
4641 ,'Attribute Value :' || engAttributeValues1(tempAttributeValueIndex) ||
4642 ':' || engAttributeValues2(tempAttributeValueIndex) || ':' || engAttributeValues3(tempAttributeValueIndex) || ':'
4643 );
4644 end if;
4645 end loop;
4646 end if;
4647 else
4648 if(isStatics(i) = ame_util.booleanTrue) then
4649 /*
4650 Write the static usage into the attribute-value package variables once for each item
4651 of the attribute's item class.
4652 */
4653 if(attributeTypes(i) = ame_util.currencyAttributeType) then
4654 ame_util.parseStaticCurAttValue(applicationIdIn => engAmeApplicationId,
4655 attributeIdIn => tempAttributeId,
4656 attributeValueIn => queryStrings(i),
4657 localErrorIn => false,
4658 amountOut => tempAttributeValue1,
4659 currencyOut => tempAttributeValue2,
4660 conversionTypeOut => tempAttributeValue3);
4661 else
4662 tempAttributeValue1 := queryStrings(i);
4663 tempAttributeValue2 := null;
4664 tempAttributeValue3 := null;
4665 end if;
4666 for j in 1 .. engItemCounts(tempItemClassIndex) loop
4667 tempAttributeValueIndex := tempAttributeValueIndex + 1;
4668 engAttributeValues1(tempAttributeValueIndex) := tempAttributeValue1;
4669 engAttributeValues2(tempAttributeValueIndex) := tempAttributeValue2;
4670 engAttributeValues3(tempAttributeValueIndex) := tempAttributeValue3;
4671 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4672 fnd_log.string
4673 (fnd_log.level_statement
4674 ,'ame_engine.fetchOtherAttributeValues'
4675 ,'Attribute Value :' || engAttributeValues1(tempAttributeValueIndex) ||
4676 ':' || engAttributeValues2(tempAttributeValueIndex) || ':' || engAttributeValues3(tempAttributeValueIndex) || ':'
4677 );
4678 end if;
4679 end loop;
4680 else
4681 tempAttributeValues1.delete;
4682 tempAttributeValues2.delete;
4683 tempAttributeValues3.delete;
4684 /*
4685 We need to do old-style dynamic PL/SQL here to make sure all occurrences of
4686 ame_util.transactionIdPlaceholder in dynamicQuery get bound.
4687 */
4688 dynamicQuery := ame_util.removeReturns(stringIn => queryStrings(i),
4689 replaceWithSpaces => true);
4690 dynamicCursor := dbms_sql.open_cursor;
4691 dbms_sql.parse(dynamicCursor,
4692 dynamicQuery,
4693 dbms_sql.native);
4694 if(instrb(dynamicQuery, ame_util.transactionIdPlaceholder) > 0) then
4695 dbms_sql.bind_variable(dynamicCursor,
4696 ame_util.transactionIdPlaceholder,
4697 engTransactionId,
4698 50); /* ame_temp_transactions.transaction_id%length doesn't work here. */
4699 end if;
4700 if(instrb(dynamicQuery, ame_util2.itemClassPlaceHolder) > 0) then
4701 dbms_sql.bind_variable(dynamicCursor,
4702 ame_util2.itemClassPlaceHolder,
4703 ame_util.headerItemClassName,
4704 50); /* ame_temp_transactions.transaction_id%length doesn't work here. */
4705 end if;
4706 if(instrb(dynamicQuery, ame_util2.itemIdPlaceHolder) > 0) then
4707 dbms_sql.bind_variable(dynamicCursor,
4708 ame_util2.itemIdPlaceHolder,
4709 engTransactionId,
4710 50); /* ame_temp_transactions.transaction_id%length doesn't work here. */
4711 end if;
4712 dbms_sql.define_array(dynamicCursor,
4713 1,
4714 tempAttributeValues1,
4715 ame_util.attributeValueTypeLength,
4716 1);
4717 if(tempAttributeType = ame_util.currencyAttributeType) then
4718 dbms_sql.define_array(dynamicCursor,
4719 2,
4720 tempAttributeValues2,
4721 ame_util.attributeValueTypeLength,
4722 1);
4723 dbms_sql.define_array(dynamicCursor,
4724 3,
4725 tempAttributeValues3,
4726 ame_util.attributeValueTypeLength,
4727 1);
4728 end if;
4729 rowsFound := dbms_sql.execute(dynamicCursor);
4730 loop
4731 rowsFound := dbms_sql.fetch_rows(dynamicCursor);
4732 dbms_sql.column_value(dynamicCursor,
4733 1,
4734 tempAttributeValues1);
4735 if(tempAttributeType = ame_util.currencyAttributeType) then
4736 dbms_sql.column_value(dynamicCursor,
4737 2,
4738 tempAttributeValues2);
4739 dbms_sql.column_value(dynamicCursor,
4740 3,
4741 tempAttributeValues3);
4742 end if;
4743 exit when rowsFound < 100;
4744 end loop;
4745 dbms_sql.close_cursor(dynamicCursor);
4746 /* Make sure the attribute usage returned the right number of rows. */
4747 if(tempAttributeValues1.count <> engItemCounts(tempItemClassIndex)) then
4748 raise rowCountException;
4749 end if;
4750 /* Transfer the attribute values into the appropriate package variables. */
4751 for j in 1 .. tempAttributeValues1.count loop
4752 tempAttributeValueIndex := tempAttributeValueIndex + 1;
4753 engAttributeValues1(tempAttributeValueIndex) := tempAttributeValues1(j);
4754 if(tempAttributeType = ame_util.currencyAttributeType) then
4755 engAttributeValues2(tempAttributeValueIndex) := tempAttributeValues2(j);
4756 engAttributeValues3(tempAttributeValueIndex) := tempAttributeValues3(j);
4757 else
4758 engAttributeValues2(tempAttributeValueIndex) := null;
4759 engAttributeValues3(tempAttributeValueIndex) := null;
4760 end if;
4761 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
4762 fnd_log.string
4763 (fnd_log.level_statement
4764 ,'ame_engine.fetchOtherAttributeValues'
4765 ,'Attribute Value :' || engAttributeValues1(tempAttributeValueIndex) ||
4766 ':' || engAttributeValues2(tempAttributeValueIndex) || ':' || engAttributeValues3(tempAttributeValueIndex) || ':'
4767 );
4768 end if;
4769 end loop;
4770 end if;
4771 end if;
4772 end if;
4773 end loop;
4774 exception
4775 when rowCountException then
4776 if(attributeCursor%isopen) then
4777 close attributeCursor;
4778 end if;
4779 if(dbms_sql.is_open(dynamicCursor)) then
4780 dbms_sql.close_cursor(dynamicCursor);
4781 end if;
4782 if(testTransCurrencyCursor%isopen) then
4783 close testTransCurrencyCursor;
4784 end if;
4785 if(testTransNonCurrencyCursor%isopen) then
4786 close testTransNonCurrencyCursor;
4787 end if;
4788 tempAttributeName := ame_attribute_pkg.getName(attributeIdIn => tempAttributeId);
4789 errorCode := -20108;
4790 errorMessage :=
4791 ame_util.getMessage(applicationShortNameIn =>'PER',
4792 messageNameIn => 'AME_400684_ATR_INV_DYN_USG',
4793 tokenNameOneIn => 'ATTRIBUTE_NAME',
4794 tokenValueOneIn => tempAttributeName);
4795 ame_util.runtimeException(packageNameIn => 'ame_engine',
4796 routineNameIn => 'fetchOtherAttributeValues',
4797 exceptionNumberIn => errorCode,
4798 exceptionStringIn => errorMessage);
4799 raise_application_error(errorCode,
4800 errorMessage);
4801 when others then
4802 if(attributeCursor%isopen) then
4803 close attributeCursor;
4804 end if;
4805 if(dbms_sql.is_open(dynamicCursor)) then
4806 dbms_sql.close_cursor(dynamicCursor);
4807 end if;
4808 if(testTransCurrencyCursor%isopen) then
4809 close testTransCurrencyCursor;
4810 end if;
4811 if(testTransNonCurrencyCursor%isopen) then
4812 close testTransNonCurrencyCursor;
4813 end if;
4814 ame_util.runtimeException(packageNameIn => 'ame_engine',
4815 routineNameIn => 'fetchOtherAttributeValues',
4816 exceptionNumberIn => sqlcode,
4817 exceptionStringIn => sqlerrm);
4818 raise;
4819 end fetchOtherAttributeValues;
4820 procedure fetchConfigVars as
4821 cursor actionTypeConfigCursor is
4822 select
4823 ame_action_type_config.action_type_id,
4824 ame_action_type_config.voting_regime,
4825 ame_action_type_config.order_number,
4826 ame_action_type_config.chain_ordering_mode,
4827 ame_action_types.name,
4828 ame_action_types.procedure_name,
4829 ame_action_type_usages.rule_type
4830 from
4831 ame_action_type_config,
4832 ame_action_types,
4833 ame_action_type_usages
4834 where
4835 ame_action_type_config.application_id = engAmeApplicationId and
4836 ame_action_types.action_type_id = ame_action_type_config.action_type_id and
4837 ame_action_type_usages.action_type_id = ame_action_types.action_type_id and
4838 /*
4839 Only action types for list-creation and exception rules have two action-type usages;
4840 all other action types have exactly one (current) action-type usage each.
4841 */
4842 ame_action_type_usages.rule_type <> ame_util.exceptionRuleType and
4843 engEffectiveRuleDate between
4844 ame_action_type_config.start_date and
4845 nvl(ame_action_type_config.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
4846 engEffectiveRuleDate between
4847 ame_action_types.start_date and
4848 nvl(ame_action_types.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
4849 engEffectiveRuleDate between
4850 ame_action_type_usages.start_date and
4851 nvl(ame_action_type_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate)
4852 order by ame_action_types.action_type_id;
4853 cursor configVarCursor is
4854 select
4855 decode(nvl(application_id,0),0,0,-1) application_id,
4856 /* modified from
4857 application_id to
4858 decode(nvl(application_id,0),0,0,-1) application_id
4859 for the bug 5614208 */
4860 variable_name,
4861 variable_value
4862 from ame_config_vars
4863 where
4864 (application_id = 0 or application_id is null or application_id = engAmeApplicationId) and
4865 /* Config vars can impact the approver list, so use engEffectiveRuleDate here. */
4866 engEffectiveRuleDate between
4867 start_date and
4868 nvl(end_date - ame_util.oneSecond, engEffectiveRuleDate)
4869 order by
4870 variable_name,
4871 application_id;
4872 appIds ame_util.idList;
4873 configVarIndex integer;
4874 variableNames ame_util.stringList;
4875 variableValues ame_util.longStringList;
4876 tempActionTypeId integer;
4877 tempActionTypeIds ame_util.idList;
4878 tempActionTypeNames ame_util.stringList;
4879 tempActionTypePackageNames ame_util.stringList;
4880 tempActionTypeUsages ame_util.idList;
4881 tempChainOrderingModes ame_util.charList;
4882 tempOrderNumbers ame_util.idList;
4883 tempVotingRegimes ame_util.charList;
4884 begin
4885 /* Fetch action-type configuration data. */
4886 open actionTypeConfigCursor;
4887 fetch actionTypeConfigCursor bulk collect
4888 into
4889 tempActionTypeIds,
4890 tempVotingRegimes,
4891 tempOrderNumbers,
4892 tempChainOrderingModes,
4893 tempActionTypeNames,
4894 tempActionTypePackageNames,
4895 tempActionTypeUsages;
4896 close actionTypeConfigCursor;
4897 for actionTypeIndex in 1 .. tempActionTypeIds.count loop
4898 tempActionTypeId := tempActionTypeIds(actionTypeIndex);
4899 engActionTypeChainOrderModes(tempActionTypeId) := tempChainOrderingModes(actionTypeIndex);
4900 engActionTypeOrderNumbers(tempActionTypeId) := tempOrderNumbers(actionTypeIndex);
4901 engActionTypeVotingRegimes(tempActionTypeId) := tempVotingRegimes(actionTypeIndex);
4902 engActionTypeNames(tempActionTypeId) := tempActionTypeNames(actionTypeIndex);
4903 engActionTypePackageNames(tempActionTypeId) := tempActionTypePackageNames(actionTypeIndex);
4904 engActionTypeUsages(tempActionTypeId) := tempActionTypeUsages(actionTypeIndex);
4905 end loop;
4906 /* Fetch configuration-variable values. */
4907 open configVarCursor;
4908 fetch configVarCursor bulk collect
4909 into
4910 appIds,
4911 variableNames,
4912 variableValues;
4913 close configVarCursor;
4914 /*
4915 This loop relies on the ordering of configVarCursor, which groups first by
4916 variable name, then by application ID. Rows with null application ID follow
4917 rows with non-null application ID in this ordering, so if a transaction type
4918 has defined a value for a configuration variable, the loop will reach this
4919 value before reaching the default value.
4920 */
4921 /*
4922 Always write the first row to the package variables. (This eliminates a
4923 comparison that would otherwise be necessary within the loop.)
4924 */
4925 engConfigVarNames(1) := variableNames(1);
4926 engConfigVarValues(1) := variableValues(1);
4927 configVarIndex := 1; /* pre-increment */
4928 for i in 2 .. variableValues.count loop
4929 if(variableNames(i) <> variableNames(i - 1)) then
4930 configVarIndex := configVarIndex + 1;
4931 engConfigVarNames(configVarIndex) := variableNames(i);
4932 engConfigVarValues(configVarIndex) := variableValues(i);
4933 if(engConfigVarNames(configVarIndex) = ame_util.forwardingConfigVar) then
4934 parseForwardingBehaviors(forwardingBehaviorsIn => engConfigVarValues(configVarIndex));
4935 elsif(engConfigVarNames(configVarIndex) = ame_util.rulePriorityModesConfigVar) then
4936 parsePriorityModes(priorityModesIn => engConfigVarValues(configVarIndex));
4937 end if;
4938 end if;
4939 end loop;
4940 exception
4941 when others then
4942 if(actionTypeConfigCursor%isopen) then
4943 close actionTypeConfigCursor;
4944 end if;
4945 if(configVarCursor%isopen) then
4946 close configVarCursor;
4947 end if;
4948 ame_util.runtimeException(packageNameIn => 'ame_engine',
4949 routineNameIn => 'fetchConfigVars',
4950 exceptionNumberIn => sqlcode,
4951 exceptionStringIn => sqlerrm);
4952 raise;
4953 end fetchConfigVars;
4954 procedure fetchDeletedApprovers as
4955 cursor deletedApproversCursor(applicationIdIn in integer,
4956 transactionIdIn in varchar2) is
4957 select
4958 name,
4959 item_class,
4960 item_id,
4961 approver_category,
4962 action_type_id,
4963 group_or_chain_id,
4964 occurrence,
4965 effective_date,
4966 reason
4967 from ame_temp_deletions
4968 where
4969 application_id = applicationIdIn and
4970 transaction_id = transactionIdIn;
4971 actionTypeIds ame_util.idList;
4972 approverCategories ame_util.charList;
4973 approverNames ame_util.longStringList;
4974 groupOrChainIds ame_util.idList;
4975 itemClasses ame_util.stringList;
4976 itemIds ame_util.stringList;
4977 occurrences ame_util.idList;
4978 upperLimit integer;
4979 tempSuppressionDateList ame_util.dateList;
4980 tempReasonList ame_util.stringList;
4981 begin
4982 open deletedApproversCursor(applicationIdIn => engAmeApplicationId,
4983 transactionIdIn => engTransactionId);
4984 fetch deletedApproversCursor bulk collect
4985 into
4986 approverNames,
4987 itemClasses,
4988 itemIds,
4989 approverCategories,
4990 actionTypeIds,
4991 groupOrChainIds,
4992 occurrences,
4993 engSuppressionDateList,
4994 engSupperssionReasonList;
4995 close deletedApproversCursor;
4996 upperLimit := actionTypeIds.count;
4997 for i in 1 .. upperLimit loop
4998 engDeletedApproverList(i).name := approverNames(i);
4999 engDeletedApproverList(i).item_class := itemClasses(i);
5000 engDeletedApproverList(i).item_id := itemIds(i);
5001 engDeletedApproverList(i).approver_category := approverCategories(i);
5002 engDeletedApproverList(i).action_type_id := actionTypeIds(i);
5003 engDeletedApproverList(i).group_or_chain_id := groupOrChainIds(i);
5004 engDeletedApproverList(i).occurrence := occurrences(i);
5005 end loop;
5006 exception
5007 when others then
5008 if(deletedApproversCursor%isopen) then
5009 close deletedApproversCursor;
5010 end if;
5011 ame_util.runtimeException(packageNameIn => 'ame_engine',
5012 routineNameIn => 'fetchDeletedApprovers',
5013 exceptionNumberIn => sqlcode,
5014 exceptionStringIn => sqlerrm);
5015 raise;
5016 end fetchDeletedApprovers;
5017 procedure fetchInsertedApprovers as
5018 cursor insertedApproversCursor(applicationIdIn in integer,
5019 transactionIdIn in varchar2) is
5020 select
5021 name,
5022 item_class,
5023 item_id,
5024 nvl(approver_category,ame_util.approvalApproverCategory) approver_category,
5025 api_insertion,
5026 authority,
5027 order_type,
5028 parameter,
5029 special_forwardee,
5030 insertion_order,
5031 effective_date,
5032 reason,
5033 approval_status
5034 from ame_temp_insertions
5035 where
5036 application_id = applicationIdIn and
5037 transaction_id = transactionIdIn
5038 order by insertion_order;
5039 approverApiInsertions ame_util.charList;
5040 approverAuthorities ame_util.charList;
5041 approverCategories ame_util.charList;
5042 approverItemClasses ame_util.stringList;
5043 approverItemIds ame_util.stringList;
5044 approverNames ame_util.longStringList;
5045 approvalStatuses ame_util.stringList;
5046 upperLimit integer;
5047 l_error_code number;
5048 errorCode integer;
5049 errorMessage ame_util.longestStringType;
5050 begin
5051 open insertedApproversCursor(applicationIdIn => engAmeApplicationId,
5052 transactionIdIn => engTransactionId);
5053 fetch insertedApproversCursor bulk collect
5054 into
5055 approverNames,
5056 approverItemClasses,
5057 approverItemIds,
5058 approverCategories,
5059 approverApiInsertions,
5060 approverAuthorities,
5061 engInsertionOrderTypeList,
5062 engInsertionParameterList,
5063 engInsertionIsSpecialForwardee,
5064 engInsertionOrderList,
5065 engInsertionDateList,
5066 engInsertionReasonList,
5067 approvalStatuses;
5068 close insertedApproversCursor;
5069 upperLimit := approverAuthorities.count;
5070 for i in 1 .. upperLimit loop
5071 engInsertedApproverList(i).name := approverNames(i);
5072 engInsertedApproverList(i).item_class := approverItemClasses(i);
5073 engInsertedApproverList(i).item_id := approverItemIds(i);
5074 engInsertedApproverList(i).approver_category := approverCategories(i);
5075 engInsertedApproverList(i).api_insertion := approverApiInsertions(i);
5076 engInsertedApproverList(i).authority := approverAuthorities(i);
5077 engInsertedApproverList(i).approval_status := approvalStatuses(i);
5078 end loop;
5079 exception
5080 when others then
5081 if(insertedApproversCursor%isopen) then
5082 close insertedApproversCursor;
5083 end if;
5084 ame_util.runtimeException(packageNameIn => 'ame_engine',
5085 routineNameIn => 'fetchInsertedApprovers',
5086 exceptionNumberIn => sqlcode,
5087 exceptionStringIn => sqlerrm);
5088 raise;
5089 end fetchInsertedApprovers;
5090 procedure fetchItemClassData as
5091 cursor itemClassUsageCursor(applicationIdIn in integer) is
5092 select
5093 ame_item_classes.item_class_id,
5094 ame_item_classes.name,
5095 ame_item_class_usages.item_id_query,
5096 ame_item_class_usages.item_class_order_number,
5097 ame_item_class_usages.item_class_par_mode,
5098 ame_item_class_usages.item_class_sublist_mode
5099 from
5100 ame_item_classes,
5101 ame_item_class_usages
5102 where
5103 ame_item_classes.item_class_id = ame_item_class_usages.item_class_id and
5104 ame_item_class_usages.application_id = applicationIdIn and
5105 engEffectiveRuleDate between
5106 ame_item_classes.start_date and
5107 nvl(ame_item_classes.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
5108 engEffectiveRuleDate between
5109 ame_item_class_usages.start_date and
5110 nvl(ame_item_class_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate)
5111 /*
5112 The order-by conditions are both critical. The second is to break
5113 item_class_order_number ties in a determinate order. Compare the
5114 attributeCursor cursor in the procedure fetchAttributeValues.
5115 */
5116 order by
5117 ame_item_class_usages.item_class_order_number,
5118 ame_item_class_usages.item_class_id;
5119 cursor testTransItemIdCursor(itemClassIdIn in integer) is
5120 select distinct item_id
5121 from ame_test_trans_att_values
5122 where
5123 application_id = engAmeApplicationId and
5124 transaction_id = engTransactionId and
5125 item_class_id = itemClassIdIn
5126 order by item_id;
5127 dynamicCursor integer;
5128 itemIdQuery ame_util.longestStringType;
5129 itemIds dbms_sql.varchar2_table;
5130 lastEngItemIdIndex integer;
5131 rowsFound integer;
5132 tempIndex integer;
5133 tempItemIdQueries ame_util.longestStringList;
5134 begin
5135 /* Fetch the item-class usages. */
5136 open itemClassUsageCursor(applicationIdIn => engAmeApplicationId);
5137 fetch itemClassUsageCursor bulk collect
5138 into
5139 engItemClassIds,
5140 engItemClassNames,
5141 tempItemIdQueries,
5142 engItemClassOrderNumbers,
5143 engItemClassParModes,
5144 engItemClassSublistModes;
5145 close itemClassUsageCursor;
5146 /* Fetch the item IDs. */
5147 lastEngItemIdIndex := null;
5148 for i in 1 .. engItemClassIds.count loop
5149 engItemClassIndexes(engItemClassIds(i)) := i;
5150 itemIds.delete;
5151 /* Fetch the current item class' item IDs into itemIds. */
5152 if(engItemClassNames(i) = ame_util.headerItemClassName) then
5153 /*
5154 The header item class should always have just one item, with the ID
5155 engTransactionId. Note that the header item class may not be the
5156 first item class, as the item classes are ordered by item-class order
5157 number. So lastEngItemIdIndex could be null.
5158 */
5159 if(lastEngItemIdIndex is null) then
5160 engItemClassItemIdIndexes(i) := 1;
5161 lastEngItemIdIndex := 1;
5162 else
5163 engItemClassItemIdIndexes(i) := lastEngItemIdIndex + 1;
5164 lastEngItemIdIndex := lastEngItemIdIndex + 1;
5165 end if;
5166 engItemIds(lastEngItemIdIndex) := engTransactionId;
5167 engItemCounts(i) := 1;
5168 else /* This item class is not the header item class. */
5169 if(engIsTestTransaction) then
5170 open testTransItemIdCursor(itemClassIdIn => engItemClassIds(i));
5171 fetch testTransItemIdCursor bulk collect into itemIds;
5172 close testTransItemIdCursor;
5173 engItemCounts(i) := itemIds.count;
5174 if(itemIds.count > 0) then
5175 if(lastEngItemIdIndex is null) then
5176 engItemClassItemIdIndexes(i) := 1;
5177 lastEngItemIdIndex := itemIds.count;
5178 else
5179 engItemClassItemIdIndexes(i) := lastEngItemIdIndex + 1;
5180 lastEngItemIdIndex := lastEngItemIdIndex + itemIds.count;
5181 end if;
5182 tempIndex := engItemClassItemIdIndexes(i); /* post-increment tempIndex */
5183 for j in 1 .. itemIds.count loop
5184 engItemIds(tempIndex) := itemIds(j);
5185 tempIndex := tempIndex + 1;
5186 end loop;
5187 else
5188 engItemClassItemIdIndexes(i) := null;
5189 end if;
5190 else
5191 itemIdQuery := ame_util.removeReturns(stringIn => tempItemIdQueries(i),
5192 replaceWithSpaces => true);
5193 dynamicCursor := dbms_sql.open_cursor;
5194 dbms_sql.parse(dynamicCursor,
5195 itemIdQuery,
5196 dbms_sql.native);
5197 if(instrb(itemIdQuery, ame_util.transactionIdPlaceholder, 1, 1) > 0) then
5198 dbms_sql.bind_variable(dynamicCursor,
5199 ame_util.transactionIdPlaceholder,
5200 engTransactionId,
5201 50); /* ame_temp_transactions.transaction_id%length doesn't work here. */
5202 end if;
5203 dbms_sql.define_array(dynamicCursor,
5204 1,
5205 itemIds,
5206 100,
5207 1);
5208 rowsFound := dbms_sql.execute(dynamicCursor);
5209 loop
5210 rowsFound := dbms_sql.fetch_rows(dynamicCursor);
5211 dbms_sql.column_value(dynamicCursor,
5212 1,
5213 itemIds);
5214 exit when rowsFound < 100;
5215 end loop;
5216 dbms_sql.close_cursor(dynamicCursor);
5217 /* Copy the item IDs into engItemIds. */
5218 engItemCounts(i) := itemIds.count;
5219 if(itemIds.count > 0) then
5220 if(lastEngItemIdIndex is null) then
5221 engItemClassItemIdIndexes(i) := 1;
5222 lastEngItemIdIndex := itemIds.count;
5223 else
5224 engItemClassItemIdIndexes(i) := lastEngItemIdIndex + 1;
5225 lastEngItemIdIndex := lastEngItemIdIndex + itemIds.count;
5226 end if;
5227 tempIndex := engItemClassItemIdIndexes(i); /* post-increment tempIndex */
5228 for j in 1 .. itemIds.count loop
5229 engItemIds(tempIndex) := itemIds(j);
5230 tempIndex := tempIndex + 1;
5231 end loop;
5232 else
5233 engItemClassItemIdIndexes(i) := null;
5234 end if;
5235 end if;
5236 end if;
5237 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
5238 fnd_log.string
5239 (fnd_log.level_statement
5240 ,'ame_engine.fetchItemClassData'
5241 ,'Item Class ::' || engItemClassNames(i) ||
5242 ':' || 'has ' || ':' || engItemCounts(i) || ':items'
5243 );
5244 end if;
5245 end loop;
5246 exception
5247 when others then
5248 if(itemClassUsageCursor%isopen) then
5249 close itemClassUsageCursor;
5250 end if;
5251 if(testTransItemIdCursor%isopen) then
5252 close testTransItemIdCursor;
5253 end if;
5254 ame_util.runtimeException(packageNameIn => 'ame_engine',
5255 routineNameIn => 'fetchItemClassData',
5256 exceptionNumberIn => sqlcode,
5257 exceptionStringIn => sqlerrm);
5258 raise;
5259 end fetchItemClassData;
5260 procedure fetchFndApplicationId(applicationIdIn in integer,
5261 fndApplicationIdOut out nocopy integer,
5262 transactionTypeIdOut out nocopy varchar2) as
5263 begin
5264 select
5265 fnd_application_id,
5266 transaction_type_id
5267 into
5268 fndApplicationIdOut,
5269 transactionTypeIdOut
5270 from ame_calling_apps
5271 where
5272 application_id = applicationIdIn and
5273 /* Don't use engEffectiveRuleDate here. */
5274 sysdate between
5275 start_date and
5276 nvl(end_date - ame_util.oneSecond, sysdate) and
5277 rownum < 2; /* Avoids second fetch otherwise required by ANSI standard to check for too many rows. */
5278 exception
5279 when others then
5280 ame_util.runtimeException(packageNameIn => 'ame_engine',
5281 routineNameIn => 'fetchFndApplicationId',
5282 exceptionNumberIn => sqlcode,
5283 exceptionStringIn => sqlerrm);
5284 fndApplicationIdOut := null;
5285 transactionTypeIdOut := null;
5286 raise;
5287 end fetchFndApplicationId;
5288 procedure fetchOldApprovers as
5289 cursor oldApproversCursor(applicationIdIn in integer,
5290 transactionIdIn in varchar2) is
5291 select
5292 name,
5293 item_class,
5294 item_id,
5295 approver_category,
5296 api_insertion,
5297 authority,
5298 approval_status,
5299 action_type_id,
5300 group_or_chain_id,
5301 occurrence
5302 from ame_temp_old_approver_lists
5303 where
5304 application_id = applicationIdIn and
5305 transaction_id = transactionIdIn
5306 order by order_number;
5307 actionTypeIds ame_util.idList;
5308 approverApiInsertions ame_util.charList;
5309 approverAuthorities ame_util.charList;
5310 approverCategories ame_util.charList;
5311 approverNames ame_util.longStringList;
5312 approverStatuses ame_util.stringList;
5313 groupOrChainIds ame_util.idList;
5314 itemClasses ame_util.stringList;
5315 itemIds ame_util.stringList;
5316 occurrences ame_util.idList;
5317 upperLimit integer;
5318 begin
5319 open oldApproversCursor(applicationIdIn => engAmeApplicationId,
5320 transactionIdIn => engTransactionId);
5321 fetch oldApproversCursor bulk collect
5322 into
5323 approverNames,
5324 itemClasses,
5325 itemIds,
5326 approverCategories,
5327 approverApiInsertions,
5328 approverAuthorities,
5329 approverStatuses,
5330 actionTypeIds,
5331 groupOrChainIds,
5332 occurrences;
5333 close oldApproversCursor;
5334 upperLimit := approverAuthorities.count;
5335 for i in 1 .. upperLimit loop
5336 engOldApproverList(i).name := approverNames(i);
5337 engOldApproverList(i).item_class := itemClasses(i);
5338 engOldApproverList(i).item_id := itemIds(i);
5339 engOldApproverList(i).approver_category := approverCategories(i);
5340 engOldApproverList(i).api_insertion := approverApiInsertions(i);
5341 engOldApproverList(i).authority := approverAuthorities(i);
5342 engOldApproverList(i).action_type_id := actionTypeIds(i);
5343 engOldApproverList(i).group_or_chain_id := groupOrChainIds(i);
5344 engOldApproverList(i).occurrence := occurrences(i);
5345 engOldApproverList(i).source := null;
5346 /* Force recalculation of suppressed and repeated statuses with each engine cycle. */
5347 if approverStatuses(i) in (ame_util.suppressedStatus, ame_util.repeatedStatus) then
5348 engOldApproverList(i).approval_status := null;
5349 else
5350 engOldApproverList(i).approval_status := approverStatuses(i);
5351 end if;
5352 end loop;
5353 exception
5354 when others then
5355 if(oldApproversCursor%isopen) then
5356 close oldApproversCursor;
5357 end if;
5358 ame_util.runtimeException(packageNameIn => 'ame_engine',
5359 routineNameIn => 'fetchOldApprovers',
5360 exceptionNumberIn => sqlcode,
5361 exceptionStringIn => sqlerrm);
5362 raise;
5363 end fetchOldApprovers;
5364 function isApproved(isDynamic in boolean
5365 ,groupIdIn in number
5366 ,origSystemIn in varchar2 default null
5367 ,origSystemIdIn in number default null
5368 ,roleNameIn in varchar2 default null) return boolean is
5369 cursor getInvalidDetails is
5370 select name
5371 from wf_local_roles
5372 where orig_system_id = origSystemIdIn
5373 and orig_system = origSystemIn
5374 and rownum <2;
5375 cursor getStatus(c_nameIn in varchar2) is
5376 select 1
5377 from dual
5378 where exists
5379 (select null
5380 from ame_trans_approval_history a
5381 where application_id = engAmeApplicationId
5382 and transaction_id = engTransactionId
5383 and group_or_chain_id = groupIdIn
5384 and name = c_nameIn
5385 and status is not null
5386 and status in (ame_util.approvedStatus
5387 ,ame_util.beatByFirstResponderStatus
5388 ,ame_util.forwardStatus
5389 ,ame_util.rejectStatus
5390 ,ame_util.approvedByRepeatedStatus
5391 ,ame_util.rejectedByRepeatedStatus
5392 ,ame_util.noResponseStatus
5393 ,ame_util2.noResponseByRepeatedStatus
5394 ,ame_util2.reassignStatus
5395 ,ame_util2.forwardByRepeatedStatus)
5396 and name = c_nameIn
5397 and row_timestamp in
5398 (select max(row_timestamp)
5399 from ame_trans_approval_history
5400 where application_id = engAmeApplicationId
5401 and transaction_id = engTransactionId
5402 and group_or_chain_id = groupIdIn
5403 and name = c_nameIn
5404 group by name
5405 ));
5406 l_name varchar2(500);
5407 l_return_status boolean := false;
5408 l_count number := 0;
5409 begin
5410 if isDynamic then
5411 open getInvalidDetails;
5412 fetch getInvalidDetails into l_name;
5413 close getInvalidDetails;
5414 if l_name is null then
5415 return false;
5416 end if;
5417 else
5418 l_name := roleNameIn;
5419 end if;
5420 open getStatus(l_name);
5421 fetch getStatus into l_count;
5422 close getStatus;
5423
5424 if l_count > 0 then
5425 return true;
5426 else
5427 return false;
5428 end if;
5429 end isApproved;
5430 procedure fetchRuntimeGroup(groupIdIn in integer) as
5431 cursor groupMemberCursor(groupIdIn in integer) is
5432 select
5433 orig_system,
5434 orig_system_id,
5435 parameter,
5436 upper(parameter_name),
5437 query_string,
5438 order_number
5439 from ame_approval_group_members
5440 where
5441 approval_group_id = groupIdIn
5442 order by order_number;
5443 badDynamicMemberException exception;
5444 dynamicCursor integer;
5445 colonLocation1 integer;
5446 colonLocation2 integer;
5447 displayNames ame_util.longStringList;
5448 errorCode integer;
5449 errorMessage ame_util.longestStringType;
5450 names ame_util.longStringList;
5451 orderNumbers ame_util.idList;
5452 origSystemIds ame_util.idList;
5453 origSystems ame_util.stringList;
5454 outputIndex integer;
5455 parameters ame_util.longStringList;
5456 queryStrings ame_util.longestStringList;
5457 rowsFound integer;
5458 tempGroupMembers dbms_sql.Varchar2_Table;
5459 upperParameterNames ame_util.stringList;
5460 tempApproverType ame_util.stringType;
5461 tempApproverId ame_util.stringType;
5462 tempname wf_roles.name%type;
5463 processFndUser boolean;
5464 l_err_code number;
5465 invgrpMemberException exception;
5466 l_isApproved boolean := false;
5467 l_name_out varchar2(400);
5468 l_display_name_out varchar2(500);
5469 l_appr_type varchar2(100);
5470 begin
5471 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
5472 fnd_log.string
5473 (fnd_log.level_statement
5474 ,'ame_engine.fetchRuntimeGroup'
5475 ,'evaluating the group::'||ame_approval_group_pkg.getName(approvalGroupIdIn => groupIdIn
5476 ,effectiveDateIn => engEffectiveRuleDate)
5477 );
5478 end if;
5479 open groupMemberCursor(groupIdIn => groupIdIn);
5480 fetch groupMemberCursor bulk collect
5481 into
5482 origSystems,
5483 origSystemIds,
5484 parameters,
5485 upperParameterNames,
5486 queryStrings,
5487 orderNumbers;
5488 close groupMemberCursor;
5489 if (engGroupUseItemBind.exists(groupIdIn)) then
5490 /* This is not the first time this query is being executed, so find and delete all old approvers in this group. */
5491 for n in 1 .. engGroupMemberGroupIds.count loop
5492 if( engGroupMemberGroupIds(n) = groupIdIn ) then
5493 -- delete all occurrences of this
5494 engGroupMemberGroupIds(n) := null;
5495 engGroupMemberNames(n) := null;
5496 engGroupMemberOrderNumbers(n) := null;
5497 engGroupMemberDisplayNames(n) := null;
5498 engGroupMemberOrigSystems(n) := null;
5499 engGroupMemberOrigSystemIds(n) := null;
5500 end if;
5501 end loop;
5502 -- compact list
5503 outputIndex := engGroupMemberGroupIds.first;
5504 for i in 1 .. engGroupMemberGroupIds.count loop
5505 if(i <> outputIndex) then /* (Don't copy a row onto itself.) */
5506 engGroupMemberGroupIds(i) := engGroupMemberGroupIds(outputIndex);
5507 engGroupMemberNames(i) := engGroupMemberNames(outputIndex);
5508 engGroupMemberOrderNumbers(i) := engGroupMemberOrderNumbers(outputIndex);
5509 engGroupMemberDisplayNames(i) := engGroupMemberDisplayNames(outputIndex);
5510 engGroupMemberOrigSystems(i) := engGroupMemberOrigSystems(outputIndex);
5511 engGroupMemberOrigSystemIds(i) := engGroupMemberOrigSystemIds(outputIndex);
5512 end if;
5513 outputIndex := engGroupMemberGroupIds.next(outputIndex);
5514 end loop;
5515 engGroupMemberGroupIds.delete(outputIndex, engGroupMemberGroupIds.count);
5516 end if;
5517 outputIndex := engGroupMemberGroupIds.count; /* pre-increment */
5518 for i in 1 .. parameters.count loop
5519 tempGroupMembers.delete; -- for bug 4616570
5520 if(upperParameterNames(i) = upper(ame_util.approverOamGroupId)) then
5521 dynamicCursor := dbms_sql.open_cursor;
5522 dbms_sql.parse(dynamicCursor,
5523 ame_util.removeReturns(stringIn => queryStrings(i),
5524 replaceWithSpaces => true),
5525 dbms_sql.native);
5526 engGroupUseItemBind(groupIdIn) := ame_util.booleanFalse;
5527 if(instrb(queryStrings(i),
5528 ame_util.transactionIdPlaceholder) > 0) then
5529 dbms_sql.bind_variable(dynamicCursor,
5530 ame_util.transactionIdPlaceholder,
5531 engTransactionId,
5532 50);
5533 end if;
5534 if(instrb(queryStrings(i),
5535 ame_util2.itemClassPlaceHolder) > 0) then
5536 dbms_sql.bind_variable(dynamicCursor,
5537 ame_util2.itemClassPlaceHolder,
5538 getItemClassName(itemClassIdIn => engAppRuleItemClassIds(engAppHandlerFirstIndex)),
5539 50);
5540 engGroupUseItemBind(groupIdIn) := ame_util.booleanTrue;
5541 end if;
5542 if(instrb(queryStrings(i),
5543 ame_util2.itemIdPlaceHolder) > 0) then
5544 dbms_sql.bind_variable(dynamicCursor,
5545 ame_util2.itemIdPlaceHolder,
5546 engAppAppItemIds(engAppHandlerFirstIndex),
5547 50);
5548 engGroupUseItemBind(groupIdIn) := ame_util.booleanTrue;
5549 end if;
5550 dbms_sql.define_array(dynamicCursor,
5551 1,
5552 tempGroupMembers,
5553 100,
5554 1);
5555 rowsFound := dbms_sql.execute(dynamicCursor);
5556 loop
5557 rowsFound := dbms_sql.fetch_rows(dynamicCursor);
5558 dbms_sql.column_value(dynamicCursor,
5559 1,
5560 tempGroupMembers);
5561 exit when rowsFound < 100;
5562 end loop;
5563 dbms_sql.close_cursor(dynamicCursor);
5564 /*
5565 Dynamic groups' query strings may return rows having one of two forms:
5566 (1) approver_type:approver_id
5567 (2) orig_system:orig_system_id
5568 */
5569 for j in 1 .. tempGroupMembers.count loop
5570 tempApproverType := null;
5571 tempApproverId := null;
5572 colonLocation1 := instrb(tempGroupMembers(j), ':', 1, 1);
5573 if(colonLocation1 = 0) then
5574 raise badDynamicMemberException;
5575 end if;
5576 tempApproverId := substrb(tempGroupMembers(j),instrb(tempGroupMembers(j), ':', 1, 1) + 1);
5577 tempApproverType := substrb(tempGroupMembers(j), 1, (instrb(tempGroupMembers(j), ':', 1, 1) - 1));
5578 begin
5579 if tempApproverType is not null and upper(tempApproverType) = upper(ame_util.approverPersonId)
5580 and tempApproverId is not null then
5581 tempName := ame_approver_type_pkg.getWfRolesName(ame_util.perOrigSystem,tempApproverId);
5582 elsif tempApproverType is not null and upper(tempApproverType) = upper(ame_util.approverUserId)
5583 and tempApproverId is not null then
5584 tempName := ame_approver_type_pkg.getWfRolesName(ame_util.fndUserOrigSystem,tempApproverId);
5585 elsif tempApproverType is not null and tempApproverId is not null then
5586 tempName := ame_approver_type_pkg.getWfRolesName(tempApproverType,tempApproverId);
5587 end if;
5588 /*following changes added for bpo instance fnd user change*/
5589 processFndUser := true;
5590 if ame_multi_tenancy_pkg.is_multi_tenant_system = ame_util.booleanTrue then
5591 if upper(tempApproverType) = upper(ame_util.approverUserId)
5592 or upper(tempApproverType) = upper(ame_util.fndUserOrigSystem) then
5593 processFndUser := false;
5594 end if;
5595 end if;
5596 if tempApproverId is not null and lengthb(trim(tempApproverId)) > 0
5597 and tempApproverType is not null and lengthb(trim(tempApproverType)) > 0
5598 and processFndUser then
5599 outputIndex := outputIndex + 1;
5600 engGroupMemberGroupIds(outputIndex) := groupIdIn;
5601 engGroupMemberOrderNumbers(outputIndex) := j;
5602 if upper(tempApproverType) = upper(ame_util.approverPersonId) then /* old style */
5603 engGroupMemberOrigSystems(outputIndex) := ame_util.perOrigSystem;
5604 engGroupMemberOrigSystemIds(outputIndex) := tempApproverId;
5605 elsif upper(tempApproverType) = upper(ame_util.approverUserId) then /* old style */
5606 engGroupMemberOrigSystems(outputIndex) := ame_util.fndUserOrigSystem;
5607 engGroupMemberOrigSystemIds(outputIndex) := tempApproverId;
5608 else /* 11i10 style */
5609 engGroupMemberOrigSystems(outputIndex) := tempApproverType;
5610 engGroupMemberOrigSystemIds(outputIndex) := tempApproverId;
5611 end if;
5612 begin
5613 ame_approver_type_pkg.getWfRolesNameAndDisplayName(
5614 origSystemIn => engGroupMemberOrigSystems(outputIndex),
5615 origSystemIdIn => engGroupMemberOrigSystemIds(outputIndex),
5616 nameOut => engGroupMemberNames(outputIndex),
5617 displayNameOut => engGroupMemberDisplayNames(outputIndex));
5618 exception
5619 when others then
5620 l_err_code := sqlcode;
5621 if l_err_code = -20213 then
5622 errorCode := -20215;
5623 errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
5624 messageNameIn => 'AME_400838_INV_APR_FOUND',
5625 tokenNameOneIn => 'PROCESS_NAME',
5626 tokenValueOneIn => 'ame_engine.fetchRuntimeGroup:'||ame_approval_group_pkg.getName
5627 (approvalGroupIdIn => groupIdIn,effectiveDateIn => engEffectiveRuleDate),
5628 tokenNameTwoIn => 'ORIG_SYSTEM',
5629 tokenValueTwoIn => tempApproverType,
5630 tokenNameThreeIn => 'ORIG_SYSEM_ID',
5631 tokenValueThreeIn => tempApproverId
5632 );
5633 raise_application_error(errorCode,errorMessage);
5634 end if;
5635 raise;
5636 end;
5637 end if;
5638 exception
5639 when others then
5640 l_err_code := sqlcode;
5641 if l_err_code = -20213 then
5642 if upper(tempApproverType) = upper(ame_util.approverPersonId) then
5643 l_appr_type := ame_util.perOrigSystem;
5644 elsif upper(tempApproverType) = upper(ame_util.approverUserId) then
5645 l_appr_type := ame_util.fndUserOrigSystem;
5646 else
5647 l_appr_type := tempApproverType;
5648 end if;
5649 l_isApproved := isApproved(isDynamic=>true,groupIdIn => groupIdIn
5650 ,origSystemIn => l_appr_type,origSystemIdIn => tempApproverId,roleNameIn => null);
5651 if not l_isApproved then
5652 errorCode := -20215;
5653 errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
5654 messageNameIn => 'AME_400838_INV_APR_FOUND',
5655 tokenNameOneIn => 'PROCESS_NAME',
5656 tokenValueOneIn => 'ame_engine.fetchRuntimeGroup:'||ame_approval_group_pkg.getName
5657 (approvalGroupIdIn => groupIdIn,effectiveDateIn => engEffectiveRuleDate),
5658 tokenNameTwoIn => 'ORIG_SYSTEM',
5659 tokenValueTwoIn => tempApproverType,
5660 tokenNameThreeIn => 'ORIG_SYSEM_ID',
5661 tokenValueThreeIn => tempApproverId
5662 );
5663 raise_application_error(errorCode,errorMessage);
5664 end if;
5665 else
5666 raise;
5667 end if;
5668 end;
5669 end loop;
5670 else /* Copy the static group into the engGroup caches. */
5671 begin
5672 ame_approver_type_pkg.getWfRolesNameAndDisplayName(
5673 origSystemIn => origSystems(i),
5674 origSystemIdIn => origSystemIds(i),
5675 nameOut => l_name_out,
5676 displayNameOut => l_display_name_out);
5677 outputIndex := outputIndex + 1;
5678 engGroupMemberNames(outputIndex) := l_name_out;
5679 engGroupMemberDisplayNames(outputIndex) := l_display_name_out;
5680 engGroupUseItemBind(groupIdIn) := ame_util.booleanFalse;
5681 engGroupMemberGroupIds(outputIndex) := groupIdIn;
5682 engGroupMemberOrderNumbers(outputIndex) := orderNumbers(i);
5683 engGroupMemberOrigSystems(outputIndex) := origSystems(i);
5684 engGroupMemberOrigSystemIds(outputIndex) := origSystemIds(i);
5685 exception
5686 when others then
5687 l_err_code := sqlcode;
5688 if l_err_code = -20213 then
5689 l_isApproved := isApproved(isDynamic=> false,groupIdIn => groupIdIn
5690 ,roleNameIn =>parameters(i));
5691 if l_err_code = -20213 then
5692 if not l_isApproved then
5693 errorCode := -20215;
5694 errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
5695 messageNameIn => 'AME_400838_INV_APR_FOUND',
5696 tokenNameOneIn => 'PROCESS_NAME',
5697 tokenValueOneIn => 'ame_engine.fetchRuntimeGroup:'||ame_approval_group_pkg.getName
5698 (approvalGroupIdIn => groupIdIn,effectiveDateIn => engEffectiveRuleDate),
5699 tokenNameTwoIn => 'ORIG_SYSTEM',
5700 tokenValueTwoIn => origSystems(i),
5701 tokenNameThreeIn => 'ORIG_SYSEM_ID',
5702 tokenValueThreeIn => origSystemIds(i)
5703 );
5704 raise_application_error(errorCode,errorMessage);
5705 end if;
5706 end if;
5707 else
5708 raise;
5709 end if;
5710 end;
5711 end if;
5712 end loop;
5713 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
5714 fnd_log.string
5715 (fnd_log.level_statement
5716 ,'ame_engine.fetchRuntimeGroup'
5717 ,'Completed the group evaluation::'||ame_approval_group_pkg.getName(approvalGroupIdIn => groupIdIn
5718 ,effectiveDateIn => engEffectiveRuleDate)
5719 );
5720 end if;
5721 exception
5722 when badDynamicMemberException then
5723 errorCode := -20109;
5724 errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
5725 messageNameIn => 'AME_400771_ENG_INVALID_DYN_GRP',
5726 tokenNameOneIn => 'GROUP_NAME',
5727 tokenValueOneIn => ame_approval_group_pkg.getName(approvalGroupIdIn => groupIdIn
5728 ,effectiveDateIn => engEffectiveRuleDate));
5729 ame_util.runtimeException(packageNameIn => 'ame_engine',
5730 routineNameIn => 'fetchRuntimeGroup',
5731 exceptionNumberIn => errorCode,
5732 exceptionStringIn => errorMessage);
5733 raise_application_error(errorCode,
5734 errorMessage);
5735 when others then
5736 if(groupMemberCursor%isopen) then
5737 close groupMemberCursor;
5738 end if;
5739 ame_util.runtimeException(packageNameIn => 'ame_engine',
5740 routineNameIn => 'fetchRuntimeGroup',
5741 exceptionNumberIn => sqlcode,
5742 exceptionStringIn => sqlerrm);
5743 raise;
5744 end fetchRuntimeGroup;
5745 /* This procedure is used to assign calculate min_order and max_order */
5746 /* of each node in the approver tree */
5747 /* It also populates the approver_order_number of the engStApprovers */
5748 procedure finalizeTree
5749 (parentIndexIn in integer default 1
5750 ,maximumOrderOut out nocopy integer
5751 ,approvalStatusOut out nocopy integer
5752 ,rejectedItemsExistOut out nocopy boolean) is
5753 currentTreeNodeIndex integer;
5754 maximumOrderOfChildren integer;
5755 approvalStatusOfChildren integer;
5756 previousTreeNodeIndex integer;
5757 currentApproverApprovalStatus varchar2(50);
5758 currentApproverCategory varchar2(1);
5759 currentApproverIndex integer;
5760 nextSuspendedItemIndex integer;
5761 hasRejectedChildren boolean;
5762 currentTreeNodeRejectionStatus boolean;
5763 begin
5764 if engStApproversTree.count > 0 then
5765 approvalStatusOfChildren := ame_util.unknownStatus;
5766 currentTreeNodeIndex := engStApproversTree(parentIndexIn).child_index;
5767 if currentTreeNodeIndex = ame_util.noChildIndex then
5768 /* This is an approver node */
5769 /* 1. For a approver node the maximum order number is same */
5770 /* as parents minimum order number */
5771 /* 2. The approvalStatus of the node is set based on */
5772 /* approvers approval status */
5773 /* 3. If the approvers approval status is ame_util.rejectStatus */
5774 /* then the approvers item class and item id are populated */
5775 /* into the global list of rejected items */
5776 maximumOrderOut := engStApproversTree(parentIndexIn).min_order;
5777 currentApproverApprovalStatus :=
5778 engStApprovers(engStApproversTree(parentIndexIn).approver_index).approval_status;
5779 currentApproverCategory :=
5780 engStApprovers(engStApproversTree(parentIndexIn).approver_index).approver_category;
5781 if currentApproverApprovalStatus is null or
5782 currentApproverApprovalStatus in (ame_util.repeatedStatus) then
5783 approvalStatusOut := ame_util.notStartedStatus;
5784 elsif currentApproverApprovalStatus in (ame_util.approvedStatus
5785 ,ame_util.rejectStatus
5786 ,ame_util.beatByFirstResponderStatus
5787 ,ame_util.approvedByRepeatedStatus
5788 ,ame_util.rejectedByRepeatedStatus
5789 ,ame_util.suppressedStatus
5790 ,ame_util.noResponseStatus
5791 ,ame_util.forwardStatus
5792 ,ame_util.approveAndForwardStatus
5793 ,ame_util2.reassignStatus
5794 ,ame_util2.noResponseByRepeatedStatus
5795 ,ame_util2.forwardByRepeatedStatus) or
5796 (currentApproverCategory = ame_util.fyiApproverCategory and
5797 (currentApproverApprovalStatus in (ame_util.notifiedStatus,
5798 ame_util.notifiedByRepeatedStatus))) then
5799 approvalStatusOut := ame_util.completedStatus;
5800 elsif currentApproverApprovalStatus not in (ame_util.approvedStatus
5801 ,ame_util.rejectStatus
5802 ,ame_util.beatByFirstResponderStatus
5803 ,ame_util.approvedByRepeatedStatus
5804 ,ame_util.rejectedByRepeatedStatus
5805 ,ame_util.suppressedStatus) then
5806 approvalStatusOut := ame_util.startedStatus;
5807 end if;
5808 if currentApproverApprovalStatus = ame_util.rejectStatus
5809 or currentApproverApprovalStatus = ame_util.rejectedByRepeatedStatus then
5810 rejectedItemsExistOut := true;
5811 /* Populate the list of rejected items and item classes */
5812 nextSuspendedItemIndex := engStSuspendedItems.count + 1;
5813 engStSuspendedItems(nextSuspendedItemIndex)
5814 := engStApprovers(engStApproversTree(parentIndexIn).approver_index).item_id;
5815 engStSuspendedItemClasses(nextSuspendedItemIndex)
5816 := engStApprovers(engStApproversTree(parentIndexIn).approver_index).item_class;
5817 else
5818 rejectedItemsExistOut := false;
5819 end if;
5820 else
5821 /* This is a non approver node */
5822 /* 1.For a non approver node find the maximum order number */
5823 /* among its children and assign it as the maximum order */
5824 /* number of the parent node */
5825 /* 2.The approvalStatus of the node is determined by finding */
5826 /* the aggregate status of all its child nodes */
5827 /* 3.The current node is flagged as rejected if any of its */
5828 /* children have a rejectedStatus */
5829 previousTreeNodeIndex := ame_util.invalidTreeIndex;
5830 currentTreeNodeRejectionStatus := false;
5831 maximumOrderOfChildren := engStApproversTree(parentIndexIn).min_order;
5832 loop
5833 if previousTreeNodeIndex = ame_util.invalidTreeIndex then
5834 engStApproversTree(currentTreeNodeIndex).min_order
5835 := engStApproversTree(parentIndexIn).min_order;
5836 elsif engStApproversTree(currentTreeNodeIndex).order_number
5837 = engStApproversTree(previousTreeNodeIndex).order_number then
5838 engStApproversTree(currentTreeNodeIndex).min_order
5839 := engStApproversTree(previousTreeNodeIndex).min_order;
5840 else
5841 engStApproversTree(currentTreeNodeIndex).min_order
5842 := maximumOrderOfChildren + 1;
5843 end if;
5844 ame_engine.finalizeTree
5845 (parentIndexIn => currentTreeNodeIndex
5846 ,maximumOrderOut => engStApproversTree(currentTreeNodeIndex).max_order
5847 ,approvalStatusOut => engStApproversTree(currentTreeNodeIndex).status
5848 ,rejectedItemsExistOut => hasRejectedChildren);
5849 if hasRejectedChildren then
5850 currentTreeNodeRejectionStatus := true;
5851 end if;
5852 if engStApproversTree(currentTreeNodeIndex).max_order
5853 > maximumOrderOfChildren then
5854 maximumOrderOfChildren := engStApproversTree(currentTreeNodeIndex).max_order;
5855 end if;
5856 if engStApproversTree(currentTreeNodeIndex).approver_index
5857 <> ame_util.noApproverIndex then
5858 currentApproverIndex := engStApproversTree(currentTreeNodeIndex).approver_index;
5859 engStApprovers(currentApproverIndex).approver_order_number
5860 := engStApproversTree(currentTreeNodeIndex).max_order;
5861 end if;
5862 if (engStApproversTree(currentTreeNodeIndex).status = ame_util.notStartedStatus
5863 and approvalStatusOfChildren = ame_util.completedStatus)
5864 or (engStApproversTree(currentTreeNodeIndex).status = ame_util.completedStatus
5865 and approvalStatusOfChildren = ame_util.notStartedStatus) then
5866 approvalStatusOfChildren := ame_util.startedStatus;
5867 elsif engStApproversTree(currentTreeNodeIndex).status
5868 > approvalStatusOfChildren then
5869 approvalStatusOfChildren := engStApproversTree(currentTreeNodeIndex).status;
5870 end if;
5871 previousTreeNodeIndex := currentTreeNodeIndex;
5872 currentTreeNodeIndex := engStApproversTree(currentTreeNodeIndex).sibling_index;
5873 exit when currentTreeNodeIndex = ame_util.noSiblingIndex;
5874 end loop;
5875 maximumOrderOut := maximumOrderOfChildren;
5876 /* If the node has supended children and the node is below the item level then */
5877 /* its status is set to completed as no more approvers are to be fetched from */
5878 /* below this node */
5879 if currentTreeNodeRejectionStatus and
5880 engStApproversTree(parentIndexIn).tree_level > 1 then
5881 approvalStatusOut := ame_util.completedStatus;
5882 elsif approvalStatusOfChildren = ame_util.unknownStatus then
5883 approvalStatusOut := ame_util.notStartedStatus;
5884 else
5885 approvalStatusOut := approvalStatusOfChildren;
5886 end if;
5887 rejectedItemsExistOut := currentTreeNodeRejectionStatus;
5888 end if;
5889 end if;
5890 exception
5891 when others then
5892 ame_util.runtimeException(packageNameIn => 'ame_engine',
5893 routineNameIn => 'finalizeTree',
5894 exceptionNumberIn => sqlcode,
5895 exceptionStringIn => sqlerrm);
5896 raise;
5897 end finalizeTree;
5898 /* getAllApprovers is for amem0013.sql backwards compatibility only. Do not use it elsewhere. */
5899 procedure getAllApprovers(approversOut out nocopy ame_util.approversTable) as
5900 begin
5901 ame_api.getAllApprovers(applicationIdIn => engAmeApplicationId,
5902 transactionIdIn => engTransactionId,
5903 transactionTypeIn => engTransactionTypeId,
5904 approversOut => approversOut);
5905 exception
5906 when others then
5907 ame_util.runtimeException(packageNameIn => 'ame_engine',
5908 routineNameIn => 'getAllApprovers',
5909 exceptionNumberIn => sqlcode,
5910 exceptionStringIn => sqlerrm);
5911 raise;
5912 end getAllApprovers;
5913 procedure getApplicableRules
5914 (ruleIdsOut out nocopy ame_util.idList
5915 ,ruleDescriptionsOut out nocopy ame_util.stringList) as
5916 nextRuleIndex integer;
5917 ruleFound boolean;
5918 begin
5919 nextRuleIndex := 1;
5920 for i in 1 .. engAppRuleIds.count loop
5921 if engRuleAppliedYN(i) = ame_util.booleanTrue then
5922 if nextRuleIndex = 1 then
5923 ruleFound := false;
5924 else
5925 ruleFound := false;
5926 for j in 1 .. (nextRuleIndex - 1) loop
5927 if ruleIdsOut(j) = engAppRuleIds(i) then
5928 ruleFound := true;
5929 exit;
5930 end if;
5931 end loop;
5932 end if;
5933 if not ruleFound then
5934 ruleIdsOut(nextRuleIndex) := engAppRuleIds(i);
5935 ruleDescriptionsOut(nextRuleIndex) := ame_rule_pkg.getDescription(ruleIdIn => engAppRuleIds(i),
5936 processingDateIn => engEffectiveRuleDate);
5937 nextRuleIndex := nextRuleIndex + 1;
5938 end if;
5939 end if;
5940 end loop;
5941 exception
5942 when others then
5943 ame_util.runtimeException(packageNameIn => 'ame_engine',
5944 routineNameIn => 'getApplicableRules',
5945 exceptionNumberIn => sqlcode,
5946 exceptionStringIn => sqlerrm);
5947 raise;
5948 end getApplicableRules;
5949 /* BUG: 4491715 sort approver categories and sources along with group ids */
5950 procedure getApprovalGroupConfigs(groupIdsInOut in out nocopy ame_util.idList,
5951 sourcesInOut in out nocopy ame_util.longStringList,
5952 approverCategoriesInOut in out nocopy ame_util.charList,
5953 orderNumbersOut out nocopy ame_util.idList,
5954 votingRegimesOut out nocopy ame_util.charList) as
5955 cursor approvalGroupConfigCursor(groupIdIn in integer) is
5956 select
5957 order_number,
5958 voting_regime
5959 from ame_approval_group_config
5960 where
5961 application_id = engAmeApplicationId and
5962 approval_group_id = groupIdIn and
5963 engEffectiveRuleDate between
5964 start_date and
5965 nvl(end_date - ame_util.oneSecond, engEffectiveRuleDate);
5966 tempGroupId integer;
5967 tempOrderNumber integer;
5968 tempVotingRegime ame_util.charType;
5969 tempSource ame_util.longStringType;
5970 tempApproverCategory ame_util.charType;
5971 upperLimit integer;
5972 begin
5973 /*
5974 Evidently it's more efficient to fetch this way, than to do a single bulk fetch
5975 with a comma-delimited list of group IDs.
5976 */
5977 for i in 1 .. groupIdsInOut.count loop
5978 open approvalGroupConfigCursor(groupIdIn => groupIdsInOut(i));
5979 fetch approvalGroupConfigCursor
5980 into
5981 orderNumbersOut(i),
5982 votingRegimesOut(i);
5983 close approvalGroupConfigCursor;
5984 end loop;
5985 /* Sort in place, first by group order number, then by group ID. */
5986 for i in 2 .. groupIdsInOut.count loop
5987 upperLimit := i - 1;
5988 for j in 1 .. upperLimit loop
5989 if(orderNumbersOut(i) < orderNumbersOut(j) or
5990 (orderNumbersOut(i) = orderNumbersOut(j) and
5991 groupIdsInOut(i) < groupIdsInOut(j))) then
5992 /* j into temps */
5993 tempGroupId := groupIdsInOut(j);
5994 tempOrderNumber := orderNumbersOut(j);
5995 tempVotingRegime := votingRegimesOut(j);
5996 tempSource := sourcesInOut(j);
5997 tempApproverCategory := approverCategoriesInOut(j);
5998 /* i into j */
5999 groupIdsInOut(j) := groupIdsInOut(i);
6000 orderNumbersOut(j) := orderNumbersOut(i);
6001 votingRegimesOut(j) := votingRegimesOut(i);
6002 sourcesInOut(j) := sourcesInOut(i);
6003 approverCategoriesInOut(j) := approverCategoriesInOut(i);
6004 /* temps into i */
6005 groupIdsInOut(i) := tempGroupId;
6006 orderNumbersOut(i) := tempOrderNumber;
6007 votingRegimesOut(i) := tempVotingRegime;
6008 sourcesInOut(i) := tempSource;
6009 approverCategoriesInOut(i) := tempApproverCategory;
6010 end if;
6011 end loop;
6012 end loop;
6013 exception
6014 when others then
6015 if(approvalGroupConfigCursor%isopen) then
6016 close approvalGroupConfigCursor;
6017 end if;
6018 ame_util.runtimeException(packageNameIn => 'ame_engine',
6019 routineNameIn => 'getApprovalGroupConfigs',
6020 exceptionNumberIn => sqlcode,
6021 exceptionStringIn => sqlerrm);
6022 raise;
6023 end getApprovalGroupConfigs;
6024 procedure getApprovers(approversOut out nocopy ame_util.approversTable2) as
6025 begin
6026 if (not engItemDataPrepared) and engPrepareItemData then
6027 prepareItemData(itemIndexesOut => engStItemIndexes
6028 ,itemItemClassesOut => engStItemClasses
6029 ,itemIdsOut => engStItemIds
6030 ,itemSourcesOut => engStItemSources);
6031 engItemDataPrepared := true;
6032 end if;
6033 prepareRuleData;
6034 preparePerApproverProductions
6035 (prodIndexesOut => engStProductionIndexes
6036 ,productionNamesOut => engStVariableNames
6037 ,productionValuesOut => engStVariableValues);
6038 for i in 1 .. engStApprovers.count loop
6039 approversOut(i).name := engStApprovers(i).name;
6040 approversOut(i).orig_system := engStApprovers(i).orig_system;
6041 approversOut(i).orig_system_id := engStApprovers(i).orig_system_id;
6042 approversOut(i).display_name := engStApprovers(i).display_name;
6043 approversOut(i).approver_category := engStApprovers(i).approver_category;
6044 approversOut(i).api_insertion := engStApprovers(i).api_insertion;
6045 approversOut(i).authority := engStApprovers(i).authority;
6046 approversOut(i).approval_status := engStApprovers(i).approval_status;
6047 approversOut(i).action_type_id := engStApprovers(i).action_type_id;
6048 approversOut(i).group_or_chain_id := engStApprovers(i).group_or_chain_id;
6049 approversOut(i).occurrence := engStApprovers(i).occurrence;
6050 approversOut(i).source := engStApprovers(i).source;
6051 approversOut(i).item_class := engStApprovers(i).item_class;
6052 approversOut(i).item_id := engStApprovers(i).item_id;
6053 approversOut(i).item_class_order_number := engStApprovers(i).item_class_order_number;
6054 approversOut(i).item_order_number := engStApprovers(i).item_order_number;
6055 approversOut(i).sub_list_order_number := engStApprovers(i).sub_list_order_number;
6056 approversOut(i).action_type_order_number := engStApprovers(i).action_type_order_number;
6057 approversOut(i).group_or_chain_order_number := engStApprovers(i).group_or_chain_order_number;
6058 approversOut(i).member_order_number := engStApprovers(i).member_order_number;
6059 approversOut(i).approver_order_number := engStApprovers(i).approver_order_number;
6060 end loop;
6061 exception
6062 when others then
6063 ame_util.runtimeException(packageNameIn => 'ame_engine',
6064 routineNameIn => 'getApprovers',
6065 exceptionNumberIn => sqlcode,
6066 exceptionStringIn => sqlerrm);
6067 raise;
6068 end getApprovers;
6069 /* This procedure returns the approvers as well as approvers tree to the calling APIs */
6070 procedure getApprovers2(approversOut out nocopy ame_util.approversTable2
6071 ,approversTreeOut out nocopy ame_util.approversTreeTable) as
6072 loopIndex integer;
6073 begin
6074 for i in 1 .. engStApprovers.count loop
6075 approversOut(i).name := engStApprovers(i).name;
6076 approversOut(i).orig_system := engStApprovers(i).orig_system;
6077 approversOut(i).orig_system_id := engStApprovers(i).orig_system_id;
6078 approversOut(i).display_name := engStApprovers(i).display_name;
6079 approversOut(i).approver_category := engStApprovers(i).approver_category;
6080 approversOut(i).api_insertion := engStApprovers(i).api_insertion;
6081 approversOut(i).authority := engStApprovers(i).authority;
6082 approversOut(i).approval_status := engStApprovers(i).approval_status;
6083 approversOut(i).action_type_id := engStApprovers(i).action_type_id;
6084 approversOut(i).group_or_chain_id := engStApprovers(i).group_or_chain_id;
6085 approversOut(i).occurrence := engStApprovers(i).occurrence;
6086 approversOut(i).source := engStApprovers(i).source;
6087 approversOut(i).item_class := engStApprovers(i).item_class;
6088 approversOut(i).item_id := engStApprovers(i).item_id;
6089 approversOut(i).item_class_order_number := engStApprovers(i).item_class_order_number;
6090 approversOut(i).item_order_number := engStApprovers(i).item_order_number;
6091 approversOut(i).sub_list_order_number := engStApprovers(i).sub_list_order_number;
6092 approversOut(i).action_type_order_number := engStApprovers(i).action_type_order_number;
6093 approversOut(i).group_or_chain_order_number := engStApprovers(i).group_or_chain_order_number;
6094 approversOut(i).member_order_number := engStApprovers(i).member_order_number;
6095 approversOut(i).approver_order_number := engStApprovers(i).approver_order_number;
6096 end loop;
6097 if engStApproversTree.count > 0 then
6098 /* Approvers Tree is sparse */
6099 loopIndex := engStApproversTree.first;
6100 loop
6101 approversTreeOut(loopIndex).parent_index := engStApproversTree(loopIndex).parent_index;
6102 approversTreeOut(loopIndex).child_index := engStApproversTree(loopIndex).child_index;
6103 approversTreeOut(loopIndex).sibling_index := engStApproversTree(loopIndex).sibling_index;
6104 approversTreeOut(loopIndex).approver_index := engStApproversTree(loopIndex).approver_index;
6105 approversTreeOut(loopIndex).tree_level := engStApproversTree(loopIndex).tree_level;
6106 approversTreeOut(loopIndex).tree_level_id := engStApproversTree(loopIndex).tree_level_id;
6107 approversTreeOut(loopIndex).order_number := engStApproversTree(loopIndex).order_number;
6108 approversTreeOut(loopIndex).min_order := engStApproversTree(loopIndex).min_order;
6109 approversTreeOut(loopIndex).max_order := engStApproversTree(loopIndex).max_order;
6110 approversTreeOut(loopIndex).status := engStApproversTree(loopIndex).status;
6111 approversTreeOut(loopIndex).is_suspended := engStApproversTree(loopIndex).is_suspended;
6112 exit when loopIndex = engStApproversTree.last;
6113 loopIndex := engStApproversTree.next(loopIndex);
6114 end loop;
6115 end if;
6116 exception
6117 when others then
6118 ame_util.runtimeException(packageNameIn => 'ame_engine',
6119 routineNameIn => 'getApprovers2',
6120 exceptionNumberIn => sqlcode,
6121 exceptionStringIn => sqlerrm);
6122 raise;
6123 end getApprovers2;
6124 procedure getHandlerCOAFirstApprover(itemClassIn in varchar2,
6125 itemIdIn in varchar2,
6126 actionTypeIdIn in integer,
6127 groupOrChainIdIn in integer,
6128 nameOut out nocopy varchar2,
6129 origSystemOut out nocopy varchar2,
6130 origSystemIdOut out nocopy integer,
6131 displayNameOut out nocopy varchar2,
6132 sourceOut out nocopy varchar2) as
6133 parameter ame_temp_insertions.parameter%type;
6134 l_error_code number;
6135 l_action_type_name varchar2(100);
6136 errorCode integer;
6137 errorMessage ame_util.longestStringType;
6138 begin
6139 parameter := ame_util.firstAuthorityParameter ||
6140 ame_util.fieldDelimiter ||
6141 itemClassIn ||
6142 ame_util.fieldDelimiter ||
6143 itemIdIn ||
6144 ame_util.fieldDelimiter ||
6145 actionTypeIdIn ||
6146 ame_util.fieldDelimiter ||
6147 groupOrChainIdIn;
6148 for i in 1 .. engInsertedApproverList.count loop
6149 if(engInsertionParameterList(i) = parameter) then
6150 nameOut := engInsertedApproverList(i).name;
6151 begin
6152 ame_approver_type_pkg.getOrigSystemIdAndDisplayName(nameIn => engInsertedApproverList(i).name,
6153 origSystemOut => origSystemOut,
6154 origSystemIdOut => origSystemIdOut,
6155 displayNameOut => displayNameOut);
6156 exception
6157 when others then
6158 l_error_code := sqlcode;
6159 if l_error_code = -20213 then
6160 l_action_type_name := getActionTypeName(actionTypeIdIn);
6161 errorCode := -20216;
6162 errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
6163 messageNameIn => 'AME_400833_INV_HANDLR_APR',
6164 tokenNameOneIn => 'ACTION_TYPE_NAME',
6165 tokenValueOneIn => l_action_type_name,
6166 tokenNameTwoIn => 'NAME',
6167 tokenValueTwoIn => engInsertedApproverList(i).name
6168 );
6169 raise_application_error(errorCode,errorMessage);
6170 end if;
6171 raise;
6172 end;
6173 sourceOut := ame_util.otherInsertion;
6174 setDeviationReasonDate(engInsertionReasonList(i),engInsertionDateList(i));
6175 return;
6176 end if;
6177 end loop;
6178 exception
6179 when others then
6180 ame_util.runtimeException(packageNameIn => 'ame_engine',
6181 routineNameIn => 'getHandlerCOAFirstApprover',
6182 exceptionNumberIn => sqlcode,
6183 exceptionStringIn => sqlerrm);
6184 raise;
6185 end getHandlerCOAFirstApprover;
6186 procedure getHandlerCOAInsertion(nameIn in varchar2,
6187 itemClassIn in varchar2,
6188 itemIdIn in varchar2,
6189 actionTypeIdIn in integer,
6190 groupOrChainIdIn in integer,
6191 occurrenceIn in integer,
6192 approvalStatusIn in varchar2,
6193 nameOut out nocopy varchar2,
6194 origSystemOut out nocopy varchar2,
6195 origSystemIdOut out nocopy integer,
6196 displayNameOut out nocopy varchar2,
6197 sourceOut out nocopy varchar2) as
6198 parameter ame_temp_insertions.parameter%type;
6199 l_error_code number;
6200 errorCode integer;
6201 errorMessage ame_util.longestStringType;
6202 l_action_type_name varchar2(200);
6203 begin
6204 parameter := nameIn ||
6205 ame_util.fieldDelimiter ||
6206 itemClassIn ||
6207 ame_util.fieldDelimiter ||
6208 itemIdIn ||
6209 ame_util.fieldDelimiter ||
6210 actionTypeIdIn ||
6211 ame_util.fieldDelimiter ||
6212 groupOrChainIdIn ||
6213 ame_util.fieldDelimiter ||
6214 occurrenceIn;
6215 for i in 1 .. engInsertedApproverList.count loop
6216 if(engInsertedApproverList(i).api_insertion = ame_util.apiAuthorityInsertion and
6217 engInsertionOrderTypeList(i) = ame_util.afterApprover and
6218 engInsertionParameterList(i) = parameter) then
6219 nameOut := engInsertedApproverList(i).name;
6220 begin
6221 ame_approver_type_pkg.getOrigSystemIdAndDisplayName(nameIn => engInsertedApproverList(i).name,
6222 origSystemOut => origSystemOut,
6223 origSystemIdOut => origSystemIdOut,
6224 displayNameOut => displayNameOut);
6225 exception
6226 when others then
6227 l_error_code := sqlcode;
6228 if l_error_code = -20213 then
6229 l_action_type_name := getActionTypeName(actionTypeIdIn);
6230 errorCode := -20217;
6231 errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
6232 messageNameIn => 'AME_400837_INV_APR_FOUND',
6233 tokenNameOneIn => 'ACTION_TYPE_NAME',
6234 tokenValueOneIn => l_action_type_name,
6235 tokenNameTwoIn => 'NAME',
6236 tokenValueTwoIn => engInsertedApproverList(i).name
6237 );
6238 raise_application_error(errorCode,errorMessage);
6239 end if;
6240 raise;
6241 end;
6242 if(engInsertionIsSpecialForwardee(i) = ame_util.booleanTrue) then
6243 sourceOut := ame_util.specialForwardInsertion;
6244 elsif(approvalStatusIn = ame_util.forwardStatus) then
6245 sourceOut := ame_util.forwardInsertion;
6246 elsif(approvalStatusIn = ame_util.approveAndForwardStatus) then
6247 sourceOut := ame_util.approveAndForwardInsertion;
6248 else
6249 sourceOut := ame_util.otherInsertion;
6250 end if;
6251 setDeviationReasonDate(engInsertionReasonList(i),engInsertionDateList(i));
6252 return;
6253 end if;
6254 end loop;
6255 exception
6256 when others then
6257 ame_util.runtimeException(packageNameIn => 'ame_engine',
6258 routineNameIn => 'getHandlerCOAInsertion',
6259 exceptionNumberIn => sqlcode,
6260 exceptionStringIn => sqlerrm);
6261 raise;
6262 end getHandlerCOAInsertion;
6263 procedure getHandlerRules(ruleIdsOut out nocopy ame_util.idList,
6264 approverCategoriesOut out nocopy ame_util.charList,
6265 parametersOut out nocopy ame_util.stringList,
6266 parameterTwosOut out nocopy ame_util.stringList) as
6267 outputIndex integer;
6268 begin
6269 outputIndex := 0;
6270 for i in engAppHandlerFirstIndex .. engAppHandlerLastIndex loop
6271 outputIndex := outputIndex + 1;
6272 ruleIdsOut(outputIndex) := engAppRuleIds(i);
6273 approverCategoriesOut(outputIndex) := engAppApproverCategories(i);
6274 parametersOut(outputIndex) := engAppParameters(i);
6275 parameterTwosOut(outputIndex) := engAppParameterTwos(i);
6276 end loop;
6277 exception
6278 when others then
6279 ame_util.runtimeException(packageNameIn => 'ame_engine',
6280 routineNameIn => 'getHandlerRules',
6281 exceptionNumberIn => sqlcode,
6282 exceptionStringIn => sqlerrm);
6283 raise;
6284 end getHandlerRules;
6285 procedure getHandlerRules2(ruleIdsOut out nocopy ame_util.idList,
6286 approverCategoriesOut out nocopy ame_util.charList,
6287 parametersOut out nocopy ame_util.stringList) as
6288 outputIndex integer;
6289 begin
6290 outputIndex := 0;
6291 for i in engAppHandlerFirstIndex .. engAppHandlerLastIndex loop
6292 outputIndex := outputIndex + 1;
6293 ruleIdsOut(outputIndex) := engAppRuleIds(i);
6294 approverCategoriesOut(outputIndex) := engAppApproverCategories(i);
6295 parametersOut(outputIndex) := engAppParameters(i);
6296 end loop;
6297 exception
6298 when others then
6299 ame_util.runtimeException(packageNameIn => 'ame_engine',
6300 routineNameIn => 'getHandlerRules2',
6301 exceptionNumberIn => sqlcode,
6302 exceptionStringIn => sqlerrm);
6303 raise;
6304 end getHandlerRules2;
6305 procedure getHandlerRules3(ruleIdsOut out nocopy ame_util.idList,
6306 ruleIndexesOut out nocopy ame_util.idList,
6307 parametersOut out nocopy ame_util.stringList,
6308 listModParameterOnesOut out nocopy ame_util.stringList,
6309 listModParameterTwosOut out nocopy ame_util.longStringList) as
6310 outputIndex integer;
6311 begin
6312 outputIndex := 0;
6313 for i in engAppHandlerFirstIndex .. engAppHandlerLastIndex loop
6314 outputIndex := outputIndex + 1;
6315 ruleIdsOut(outputIndex) := engAppRuleIds(i);
6316 ruleIndexesOut(outputIndex) := i;
6317 parametersOut(outputIndex) := engAppParameters(i);
6318 getLMCondition(ruleIdIn => engAppRuleIds(i),
6319 parameterOneOut => listModParameterOnesOut(outputIndex),
6320 parameterTwoOut => listModParameterTwosOut(outputIndex));
6321 end loop;
6322 exception
6323 when others then
6324 ame_util.runtimeException(packageNameIn => 'ame_engine',
6325 routineNameIn => 'getHandlerRules3',
6326 exceptionNumberIn => sqlcode,
6327 exceptionStringIn => sqlerrm);
6328 raise;
6329 end getHandlerRules3;
6330 procedure getHandlerLMApprovers(listModParameterOneIn in varchar2,
6331 listModParameterTwoIn in varchar2,
6332 includeFyiApproversIn in boolean,
6333 includeApprovalGroupsIn in boolean,
6334 returnForwardeesIn in boolean,
6335 approverIndexesOut out nocopy ame_util.idList,
6336 lastForwardeeIndexesOut out nocopy ame_util.idList) as
6337 currentActionTypeId integer;
6338 currentGroupOrChainId integer;
6339 currentIndex integer;
6340 currentTargetIndex integer;
6341 engStApproversCount integer;
6342 outputIndex integer;
6343 begin
6344 engStApproversCount := engStApprovers.count;
6345 if(engStApproversCount = 0) then
6346 return;
6347 end if;
6348 outputIndex := 0; /* pre-increment */
6349 currentIndex := 1; /* post-increment */
6350 loop
6351 if((engStApprovers(currentIndex).approver_category = ame_util.approvalApproverCategory or
6352 includeFyiApproversIn) and
6353 (engStApprovers(currentIndex).authority = ame_util.authorityApprover or
6354 includeApprovalGroupsIn) and
6355 listModParameterTwoIn = engStApprovers(currentIndex).name) then
6356 /* This approver matches the input approver, and satisfies the input boolean arguments. */
6357 currentTargetIndex := currentIndex;
6358 currentGroupOrChainId := engStApprovers(currentTargetIndex).group_or_chain_id;
6359 currentActionTypeId := engStApprovers(currentTargetIndex).action_type_id;
6360 if(returnForwardeesIn) then
6361 /*
6362 Set currentIndex to the index of the last of any subsequent forwardees. Start the loop
6363 at the target to check whether the target forwards. (Note that we necessarily stay
6364 in the same approval group or chain of authority as long as we're forwarding.)
6365 */
6366 for i in currentTargetIndex .. engStApproversCount loop
6367 if(engStApprovers(currentIndex).approval_status in (ame_util.forwardStatus,
6368 ame_util.approveAndForwardStatus)) then
6369 currentIndex := i;
6370 else
6371 exit;
6372 end if;
6373 end loop;
6374 end if;
6375 /*
6376 Now increment currentIndex to point to the approver after the target, or after the target's
6377 forwarding chain if necessary. (This may point past the end of the list; check for that.)
6378 This also serves to increment currentIndex for the outer loop.
6379 */
6380 currentIndex := currentIndex + 1;
6381 /*
6382 If the target approver satisfies listModParameterOneIn, output the target approver and
6383 optionally the last forwardee.
6384 */
6385 /*
6386 All but the first of the conditions in the following if statement
6387 are for the ame_util.finalApprover case.
6388 */
6389 if(listModParameterOneIn = ame_util.anyApprover or
6390 currentIndex > engStApproversCount or
6391 engStApprovers(currentIndex).group_or_chain_id <> currentGroupOrChainId or
6392 engStApprovers(currentIndex).action_type_id <> currentActionTypeId or
6393 engStApprovers(currentIndex).item_id <> engStApprovers(currentTargetIndex).item_id or
6394 engStApprovers(currentIndex).item_class <> engStApprovers(currentTargetIndex).item_class) then
6395 /* Output the approver(s). */
6396 outputIndex := outputIndex + 1;
6397 approverIndexesOut(outputIndex) := currentTargetIndex;
6398 if(returnForwardeesIn) then
6399 lastForwardeeIndexesOut(outputIndex) := currentIndex - 1;
6400 end if;
6401 end if;
6402 else /* Just iterate. */
6403 currentIndex := currentIndex + 1;
6404 end if;
6405 /* Exit the loop upon reaching the end of engStApprovers. */
6406 if(currentIndex > engStApproversCount) then
6407 exit;
6408 end if;
6409 end loop;
6410 exception
6411 when others then
6412 ame_util.runtimeException(packageNameIn => 'ame_engine',
6413 routineNameIn => 'getHandlerLMApprovers',
6414 exceptionNumberIn => sqlcode,
6415 exceptionStringIn => sqlerrm);
6416 raise;
6417 end getHandlerLMApprovers;
6418 procedure getHeaderAttValues1(attributeIdIn in integer,
6419 attributeValue1Out out nocopy varchar2,
6420 attributeValue2Out out nocopy varchar2,
6421 attributeValue3Out out nocopy varchar2) as
6422 attributeValueIndex integer;
6423 begin
6424 attributeValueIndex := engAttributeValueIndexes(attributeIdIn);
6425 attributeValue1Out := engAttributeValues1(attributeValueIndex);
6426 attributeValue2Out := engAttributeValues2(attributeValueIndex);
6427 attributeValue3Out := engAttributeValues3(attributeValueIndex);
6428 exception
6429 when others then
6430 ame_util.runtimeException(packageNameIn => 'ame_engine',
6431 routineNameIn => 'getHeaderAttValues1',
6432 exceptionNumberIn => sqlcode,
6433 exceptionStringIn => sqlerrm);
6434 raise;
6435 end getHeaderAttValues1;
6436 procedure getHeaderAttValues2(attributeNameIn in varchar2,
6437 attributeValue1Out out nocopy varchar2,
6438 attributeValue2Out out nocopy varchar2,
6439 attributeValue3Out out nocopy varchar2) as
6440 attributeValueIndex integer;
6441 begin
6442 if (engAttributeVariant.exists(getAttributeIdByName(attributeNameIn => attributeNameIn))) then
6443 /* fetch the new attribute value */
6444 attributeValue1Out := getVariantAttributeValue(attributeIdIn => getAttributeIdByName(attributeNameIn => attributeNameIn),
6445 itemClassIn => getItemClassName(itemClassIdIn => engAppRuleItemClassIds(engAppHandlerFirstIndex)),
6446 itemIdIn => engAppAppItemIds(engAppHandlerFirstIndex) );
6447 attributeValue2Out := null;
6448 attributeValue3Out := null;
6449 else
6450 attributeValueIndex := engAttributeValueIndexes(getAttributeIdByName(attributeNameIn => attributeNameIn));
6451 attributeValue1Out := engAttributeValues1(attributeValueIndex);
6452 attributeValue2Out := engAttributeValues2(attributeValueIndex);
6453 attributeValue3Out := engAttributeValues3(attributeValueIndex);
6454 end if;
6455 exception
6456 when others then
6457 ame_util.runtimeException(packageNameIn => 'ame_engine',
6458 routineNameIn => 'getHeaderAttValues2',
6459 exceptionNumberIn => sqlcode,
6460 exceptionStringIn => sqlerrm);
6461 raise;
6462 end getHeaderAttValues2;
6463 procedure getItemAppProcessCompleteYN(itemAppProcessCompleteYNOut out nocopy ame_util.charList) as
6464 begin
6465 for i in 1 .. engStItemAppProcessCompleteYN.count loop
6466 itemAppProcessCompleteYNOut(i) := engStItemAppProcessCompleteYN(i);
6467 end loop;
6468 exception
6469 when others then
6470 ame_util.runtimeException(packageNameIn => 'ame_engine',
6471 routineNameIn => 'getItemAppProcessCompleteYN',
6472 exceptionNumberIn => sqlcode,
6473 exceptionStringIn => sqlerrm);
6474 raise;
6475 end getItemAppProcessCompleteYN;
6476 procedure getItemAttValues1(attributeIdIn in integer,
6477 itemIdIn in varchar2,
6478 attributeValue1Out out nocopy varchar2,
6479 attributeValue2Out out nocopy varchar2,
6480 attributeValue3Out out nocopy varchar2) as
6481 attributeValueIndex integer;
6482 begin
6483 attributeValueIndex :=
6484 engAttributeValueIndexes(attributeIdIn) +
6485 getItemOffset(itemClassIdIn => engAttributeItemClassIds(attributeIdIn),
6486 itemIdIn => itemIdIn);
6487 attributeValue1Out := engAttributeValues1(attributeValueIndex);
6488 attributeValue2Out := engAttributeValues2(attributeValueIndex);
6489 attributeValue3Out := engAttributeValues3(attributeValueIndex);
6490 exception
6491 when others then
6492 ame_util.runtimeException(packageNameIn => 'ame_engine',
6493 routineNameIn => 'getItemAttValues1',
6494 exceptionNumberIn => sqlcode,
6495 exceptionStringIn => sqlerrm);
6496 raise;
6497 end getItemAttValues1;
6498 procedure getItemAttValues2(attributeNameIn in varchar2,
6499 itemIdIn in varchar2,
6500 attributeValue1Out out nocopy varchar2,
6501 attributeValue2Out out nocopy varchar2,
6502 attributeValue3Out out nocopy varchar2) as
6503 attributeId integer;
6504 attributeValueIndex integer;
6505 begin
6506 attributeId := getAttributeIdByName(attributeNameIn => attributeNameIn);
6507 attributeValueIndex :=
6508 engAttributeValueIndexes(attributeId) +
6509 getItemOffset(itemClassIdIn => engAttributeItemClassIds(attributeId),
6510 itemIdIn => itemIdIn);
6511 attributeValue1Out := engAttributeValues1(attributeValueIndex);
6512 attributeValue2Out := engAttributeValues2(attributeValueIndex);
6513 attributeValue3Out := engAttributeValues3(attributeValueIndex);
6514 exception
6515 when others then
6516 ame_util.runtimeException(packageNameIn => 'ame_engine',
6517 routineNameIn => 'getItemAttValues2',
6518 exceptionNumberIn => sqlcode,
6519 exceptionStringIn => sqlerrm);
6520 raise;
6521 end getItemAttValues2;
6522 procedure getItemAttValues3(attributeIdIn in integer,
6523 itemIndexIn in varchar2,
6524 attributeValue1Out out nocopy varchar2,
6525 attributeValue2Out out nocopy varchar2,
6526 attributeValue3Out out nocopy varchar2) as
6527 attributeValueIndex integer;
6528 begin
6529 attributeValueIndex :=
6530 engAttributeValueIndexes(attributeIdIn) +
6531 itemIndexIn -
6532 engItemClassItemIdIndexes(engItemClassIndexes(engAttributeItemClassIds(attributeIdIn)));
6533 attributeValue1Out := engAttributeValues1(attributeValueIndex);
6534 attributeValue2Out := engAttributeValues2(attributeValueIndex);
6535 attributeValue3Out := engAttributeValues3(attributeValueIndex);
6536 exception
6537 when others then
6538 ame_util.runtimeException(packageNameIn => 'ame_engine',
6539 routineNameIn => 'getItemAttValues3',
6540 exceptionNumberIn => sqlcode,
6541 exceptionStringIn => sqlerrm);
6542 raise;
6543 end getItemAttValues3;
6544 procedure getItemClassAttValues1(attributeIdIn in integer,
6545 attributeValuesOut out nocopy ame_util.attributeValueList) as
6546 outputIndex integer;
6547 begin
6548 outputIndex := 0; /* pre-increment */
6549 for i in
6550 engAttributeValueIndexes(attributeIdIn) ..
6551 (engAttributeValueIndexes(attributeIdIn) +
6552 engItemCounts(engItemClassIndexes(engAttributeItemClassIds(attributeIdIn))) -
6553 1) loop
6554 outputIndex := outputIndex + 1;
6555 attributeValuesOut(outputIndex) := engAttributeValues1(i);
6556 end loop;
6557 exception
6558 when others then
6559 ame_util.runtimeException(packageNameIn => 'ame_engine',
6560 routineNameIn => 'getItemClassAttValues1',
6561 exceptionNumberIn => sqlcode,
6562 exceptionStringIn => sqlerrm);
6563 raise;
6564 end getItemClassAttValues1;
6565 procedure getItemClassAttValues2(attributeNameIn in varchar2,
6566 attributeValuesOut out nocopy ame_util.attributeValueList) as
6567 attributeId integer;
6568 outputIndex integer;
6569 begin
6570 attributeId := getAttributeIdByName(attributeNameIn => attributeNameIn);
6571 outputIndex := 0; /* pre-increment */
6572 for i in
6573 engAttributeValueIndexes(attributeId) ..
6574 (engAttributeValueIndexes(attributeId) +
6575 engItemCounts(engItemClassIndexes(engAttributeItemClassIds(attributeId))) -
6576 1) loop
6577 outputIndex := outputIndex + 1;
6578 attributeValuesOut(outputIndex) := engAttributeValues1(i);
6579 end loop;
6580 exception
6581 when others then
6582 ame_util.runtimeException(packageNameIn => 'ame_engine',
6583 routineNameIn => 'getItemClassAttValues2',
6584 exceptionNumberIn => sqlcode,
6585 exceptionStringIn => sqlerrm);
6586 raise;
6587 end getItemClassAttValues2;
6588 procedure getItemClassAttValues3(attributeIdIn in integer,
6589 attributeValues1Out out nocopy ame_util.attributeValueList,
6590 attributeValues2Out out nocopy ame_util.attributeValueList,
6591 attributeValues3Out out nocopy ame_util.attributeValueList) as
6592 outputIndex integer;
6593 begin
6594 outputIndex := 0; /* pre-increment */
6595 for i in
6596 engAttributeValueIndexes(attributeIdIn) ..
6597 (engAttributeValueIndexes(attributeIdIn) +
6598 engItemCounts(engItemClassIndexes(engAttributeItemClassIds(attributeIdIn))) -
6599 1) loop
6600 outputIndex := outputIndex + 1;
6601 attributeValues1Out(outputIndex) := engAttributeValues1(i);
6602 attributeValues2Out(outputIndex) := engAttributeValues2(i);
6603 attributeValues3Out(outputIndex) := engAttributeValues3(i);
6604 end loop;
6605 exception
6606 when others then
6607 ame_util.runtimeException(packageNameIn => 'ame_engine',
6608 routineNameIn => 'getItemClassAttValues3',
6609 exceptionNumberIn => sqlcode,
6610 exceptionStringIn => sqlerrm);
6611 raise;
6612 end getItemClassAttValues3;
6613 procedure getItemClassAttValues4(attributeNameIn in varchar2,
6614 attributeValues1Out out nocopy ame_util.attributeValueList,
6615 attributeValues2Out out nocopy ame_util.attributeValueList,
6616 attributeValues3Out out nocopy ame_util.attributeValueList) as
6617 attributeId integer;
6618 outputIndex integer;
6619 begin
6620 attributeId := getAttributeIdByName(attributeNameIn => attributeNameIn);
6621 outputIndex := 0; /* pre-increment */
6622 for i in
6623 engAttributeValueIndexes(attributeId) ..
6624 (engAttributeValueIndexes(attributeId) +
6625 engItemCounts(engItemClassIndexes(engAttributeItemClassIds(attributeId))) -
6626 1) loop
6627 outputIndex := outputIndex + 1;
6628 attributeValues1Out(outputIndex) := engAttributeValues1(i);
6629 attributeValues2Out(outputIndex) := engAttributeValues2(i);
6630 attributeValues3Out(outputIndex) := engAttributeValues3(i);
6631 end loop;
6632 exception
6633 when others then
6634 ame_util.runtimeException(packageNameIn => 'ame_engine',
6635 routineNameIn => 'getItemClassAttValues4',
6636 exceptionNumberIn => sqlcode,
6637 exceptionStringIn => sqlerrm);
6638 raise;
6639 end getItemClassAttValues4;
6640 procedure getItemClassItemIds(itemClassIdIn in integer,
6641 itemIdsOut out nocopy ame_util.stringList) as
6642 firstItemIndex integer;
6643 itemClassIndex integer;
6644 tempIndex integer;
6645 begin
6646 itemClassIndex := engItemClassIndexes(itemClassIdIn);
6647 firstItemIndex := engItemClassItemIdIndexes(itemClassIndex);
6648 if(firstItemIndex is not null) then
6649 tempIndex := 0; /* pre-increment */
6650 for itemIndex in
6651 firstItemIndex ..
6652 (firstItemIndex + engItemCounts(itemClassIndex) - 1) loop
6653 tempIndex := tempIndex + 1;
6654 itemIdsOut(tempIndex) := engItemIds(itemIndex);
6655 end loop;
6656 end if;
6657 exception
6658 when others then
6659 itemIdsOut.delete;
6660 ame_util.runtimeException(packageNameIn => 'ame_engine',
6661 routineNameIn => 'getItemClassItemIds',
6662 exceptionNumberIn => sqlcode,
6663 exceptionStringIn => sqlerrm);
6664 raise;
6665 end getItemClassItemIds;
6666 procedure getItemClasses(itemClassesOut out nocopy ame_util.stringList) as
6667 begin
6668 for i in 1 .. engStItemClasses.count loop
6669 itemClassesOut(i) := engStItemClasses(i);
6670 end loop;
6671 exception
6672 when others then
6673 ame_util.runtimeException(packageNameIn => 'ame_engine',
6674 routineNameIn => 'getItemClasses',
6675 exceptionNumberIn => sqlcode,
6676 exceptionStringIn => sqlerrm);
6677 raise;
6678 end getItemClasses;
6679 procedure getItemIds(itemIdsOut out nocopy ame_util.stringList) as
6680 begin
6681 for i in 1 .. engStItemIds.count loop
6682 itemIdsOut(i) := engStItemIds(i);
6683 end loop;
6684 exception
6685 when others then
6686 ame_util.runtimeException(packageNameIn => 'ame_engine',
6687 routineNameIn => 'getItemIds',
6688 exceptionNumberIn => sqlcode,
6689 exceptionStringIn => sqlerrm);
6690 raise;
6691 end getItemIds;
6692 procedure getItemIndexes(itemIndexesOut out nocopy ame_util.idList) as
6693 begin
6694 for i in 1 .. engStItemIndexes.count loop
6695 itemIndexesOut(i) := engStItemIndexes(i);
6696 end loop;
6697 exception
6698 when others then
6699 ame_util.runtimeException(packageNameIn => 'ame_engine',
6700 routineNameIn => 'getItemIndexes',
6701 exceptionNumberIn => sqlcode,
6702 exceptionStringIn => sqlerrm);
6703 raise;
6704 end getItemIndexes;
6705 procedure getItemSources(itemSourcesOut out nocopy ame_util.longStringList) as
6706 begin
6707 for i in 1 .. engStItemSources.count loop
6708 itemSourcesOut(i) := engStItemSources(i);
6709 end loop;
6710 exception
6711 when others then
6712 ame_util.runtimeException(packageNameIn => 'ame_engine',
6713 routineNameIn => 'getItemSources',
6714 exceptionNumberIn => sqlcode,
6715 exceptionStringIn => sqlerrm);
6716 raise;
6717 end getItemSources;
6718 procedure getAllItemClasses(itemClassNamesOut out nocopy ame_util.stringList) as
6719 tempIndex integer;
6720 tempCount integer;
6721 begin
6722 tempIndex := 0;
6723 tempCount := 0;
6724 for i in 1 .. engItemClassIds.count loop
6725 tempCount := engItemCounts(engItemClassIndexes(engItemClassIds(i)));
6726 tempIndex := itemClassNamesOut.count;
6727 for x in 1 .. tempCount loop
6728 itemClassNamesOut(tempIndex + x) := engItemClassNames(i);
6729 end loop;
6730 end loop;
6731 exception
6732 when others then
6733 ame_util.runtimeException(packageNameIn => 'ame_engine',
6734 routineNameIn => 'getAllItemClasses',
6735 exceptionNumberIn => sqlcode,
6736 exceptionStringIn => sqlerrm);
6737 raise;
6738 end getAllItemClasses;
6739 procedure getAllItemIds(itemIdsOut out nocopy ame_util.stringList) as
6740 begin
6741 for i in 1 .. engItemIds.count loop
6742 itemIdsOut(i) := engItemIds(i);
6743 end loop;
6744 exception
6745 when others then
6746 ame_util.runtimeException(packageNameIn => 'ame_engine',
6747 routineNameIn => 'getAllItemIds',
6748 exceptionNumberIn => sqlcode,
6749 exceptionStringIn => sqlerrm);
6750 raise;
6751 end getAllItemIds;
6752 procedure getInsertions
6753 (positionIn in number
6754 ,orderTypeIn in varchar2 default null
6755 ,coaInsertionsYNIn in varchar2 default ame_util.booleanTrue
6756 ,availableInsertionsOut out nocopy ame_util.insertionsTable2
6757 ) as
6758
6759 engStApproversCount integer;
6760 availableInsertionsIndex integer; /* pre-increment */
6761 errorCode integer;
6762 errorMessage ame_util.longestStringType;
6763 invalidPositionException exception;
6764 nextApproverDescription ame_temp_insertions.description%type;
6765 prevApproverDescription ame_temp_insertions.description%type;
6766 ruleIdList ame_util.idList;
6767 sourceDescription ame_util.stringType;
6768 tempBoolean boolean;
6769 tempInsertionDoesNotExist boolean;
6770 tempParameter ame_temp_insertions.parameter%type;
6771 l_error_code number;
6772 begin
6773
6774 engStApproversCount := engStApprovers.count;
6775
6776 if(positionIn < 1 or
6777 positionIn > engStApproversCount + 1 or
6778 not ame_util.isANonNegativeInteger(stringIn => positionIn)) then
6779 raise invalidPositionException;
6780 end if;
6781
6782 availableInsertionsIndex := 0;
6783
6784 if (orderTypeIn is null or
6785 orderTypeIn = ame_util.absoluteOrder) then
6786
6787 tempParameter := positionIn;
6788 if (engStApproversCount = 0) then
6789
6790 /* pre-approver */
6791 if (not ame_engine.insertionExists
6792 (orderTypeIn => ame_util.absoluteOrder
6793 ,parameterIn => tempParameter
6794 )) then
6795 availableInsertionsIndex := availableInsertionsIndex + 1;
6796 availableInsertionsOut(availableInsertionsIndex).item_class := ame_util.headerItemClassName;
6797 availableInsertionsOut(availableInsertionsIndex).item_id := engTransactionId;
6798 availableInsertionsOut(availableInsertionsIndex).action_type_id := null;
6799 availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := null;
6800 availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.absoluteOrder;
6801 availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
6802 availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
6803 availableInsertionsOut(availableInsertionsIndex).authority := ame_util.preApprover;
6804 availableInsertionsOut(availableInsertionsIndex).description :=
6805 ame_util.absoluteOrderDescription || positionIn || '. ';
6806 end if;
6807
6808 /* authority approver */
6809 if (not ame_engine.insertionExists
6810 (orderTypeIn => ame_util.absoluteOrder
6811 ,parameterIn => tempParameter
6812 )) then
6813 availableInsertionsIndex := availableInsertionsIndex + 1;
6814 availableInsertionsOut(availableInsertionsIndex).item_class := ame_util.headerItemClassName;
6815 availableInsertionsOut(availableInsertionsIndex).item_id := engTransactionId;
6816 availableInsertionsOut(availableInsertionsIndex).action_type_id := null;
6817 availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := null;
6818 availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.absoluteOrder;
6819 availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
6820 availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
6821 availableInsertionsOut(availableInsertionsIndex).authority := ame_util.authorityApprover;
6822 availableInsertionsOut(availableInsertionsIndex).description :=
6823 ame_util.absoluteOrderDescription || positionIn || '. ';
6824 end if;
6825
6826 /* post approver */
6827 if (not ame_engine.insertionExists
6828 (orderTypeIn => ame_util.absoluteOrder
6829 ,parameterIn => tempParameter
6830 )) then
6831 availableInsertionsIndex := availableInsertionsIndex + 1;
6832 availableInsertionsOut(availableInsertionsIndex).item_class := ame_util.headerItemClassName;
6833 availableInsertionsOut(availableInsertionsIndex).item_id := engTransactionId;
6834 availableInsertionsOut(availableInsertionsIndex).action_type_id := null;
6835 availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := null;
6836 availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.absoluteOrder;
6837 availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
6838 availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
6839 availableInsertionsOut(availableInsertionsIndex).authority := ame_util.postApprover;
6840 availableInsertionsOut(availableInsertionsIndex).description :=
6841 ame_util.absoluteOrderDescription || positionIn || '. ';
6842 end if;
6843
6844 else /* If approver count is more than zero */
6845
6846 if (positionIn < engStApproversCount + 1) then
6847
6848 /* Attribute to the insertee the relevant properties of the approver at positionIn. */
6849 if (not ame_engine.insertionExists
6850 (orderTypeIn => ame_util.absoluteOrder
6851 ,parameterIn => tempParameter
6852 )) then
6853 availableInsertionsIndex := availableInsertionsIndex + 1;
6854 availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn).item_class;
6855 availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn).item_id;
6856 availableInsertionsOut(availableInsertionsIndex).action_type_id := engStApprovers(positionIn).action_type_id;
6857 availableInsertionsOut(availableInsertionsIndex).group_or_chain_id :=
6858 engStApprovers(positionIn).group_or_chain_id;
6859 availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.absoluteOrder;
6860 availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
6861 availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
6862 availableInsertionsOut(availableInsertionsIndex).authority := engStApprovers(positionIn).authority;
6863 availableInsertionsOut(availableInsertionsIndex).description :=
6864 ame_util.absoluteOrderDescription || positionIn || '. ';
6865 end if;
6866
6867 end if;
6868
6869 /*
6870 If there is an approver at positionIn - 1, and the approver's relevant properties differ from
6871 those of the approver at positionIn (if any), add a second available insertion, attributing
6872 to the insertee the relevant properties of engStApprovers(positionIn - 1).
6873 */
6874 if (positionIn = engStApproversCount + 1 or
6875 (positionIn > 1 and
6876 (engStApprovers(positionIn).group_or_chain_id <> engStApprovers(positionIn - 1).group_or_chain_id or
6877 engStApprovers(positionIn).action_type_id <> engStApprovers(positionIn - 1).action_type_id or
6878 engStApprovers(positionIn).item_id <> engStApprovers(positionIn - 1).item_id or
6879 engStApprovers(positionIn).item_class <> engStApprovers(positionIn - 1).item_class
6880 ))) then
6881
6882 /* Attribute to the insertee the relevant properties of the approver at positionIn - 1. */
6883 if (not ame_engine.insertionExists
6884 (orderTypeIn => ame_util.absoluteOrder
6885 ,parameterIn => tempParameter
6886 )) then
6887 availableInsertionsIndex := availableInsertionsIndex + 1;
6888 availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn - 1).item_class;
6889 availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn - 1).item_id;
6890 availableInsertionsOut(availableInsertionsIndex).action_type_id :=
6891 engStApprovers(positionIn - 1).action_type_id;
6892 availableInsertionsOut(availableInsertionsIndex).group_or_chain_id :=
6893 engStApprovers(positionIn - 1).group_or_chain_id;
6894 availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.absoluteOrder;
6895 availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
6896 availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
6897 availableInsertionsOut(availableInsertionsIndex).authority := engStApprovers(positionIn - 1).authority;
6898 availableInsertionsOut(availableInsertionsIndex).description :=
6899 ame_util.absoluteOrderDescription || positionIn || '. ';
6900 end if;
6901 end if;
6902 end if; /* End if approver count > 0 */
6903
6904 end if; /* End if order type is absolute Order */
6905
6906 /*
6907 ORDER TYPE: afterApprover
6908 Ad-hoc afterApprover is available if positionIn > 1. COA afterApprover is available if also
6909 the approver at positionIn - 1 is a COA approvalApproverCategory approver.
6910 */
6911 if (orderTypeIn is null or
6912 orderTypeIn = ame_util.afterApprover) then
6913
6914 if (positionIn = 1 or
6915 engStApproversCount = 0) then
6916 prevApproverDescription := null;
6917 else
6918 begin
6919 prevApproverDescription :=
6920 ame_approver_type_pkg.getApproverDisplayName(nameIn => engStApprovers(positionIn - 1).name);
6921
6922 exception
6923 when others then
6924 l_error_code := sqlcode;
6925 if l_error_code = 20213 then
6926 errorCode := -20218;
6927 errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
6928 messageNameIn => 'AME_400837_INV_APR_FOUND',
6929 tokenNameOneIn => 'PROCESS_NAME',
6930 tokenValueOneIn => 'ame_engine.getInsertions',
6931 tokenNameTwoIn => 'NAME',
6932 tokenValueTwoIn => engStApprovers(positionIn - 1).name);
6933 raise_application_error(errorCode,errorMessage);
6934 end if;
6935 raise;
6936 end;
6937 end if;
6938
6939 if(positionIn > 1) then /* ad-hoc */
6940
6941 tempParameter := engStApprovers(positionIn - 1).name ||
6942 ame_util.fieldDelimiter ||
6943 engStApprovers(positionIn - 1).item_class ||
6944 ame_util.fieldDelimiter ||
6945 engStApprovers(positionIn - 1).item_id ||
6946 ame_util.fieldDelimiter ||
6947 engStApprovers(positionIn - 1).action_type_id ||
6948 ame_util.fieldDelimiter ||
6949 engStApprovers(positionIn - 1).group_or_chain_id ||
6950 ame_util.fieldDelimiter ||
6951 engStApprovers(positionIn - 1).occurrence;
6952
6953 if (not ame_engine.insertionExists
6954 (orderTypeIn => ame_util.afterApprover
6955 ,parameterIn => tempParameter
6956 )) then
6957 availableInsertionsIndex := availableInsertionsIndex + 1;
6958 availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn - 1).item_class;
6959 availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn - 1).item_id;
6960 availableInsertionsOut(availableInsertionsIndex).action_type_id :=
6961 engStApprovers(positionIn - 1).action_type_id;
6962 availableInsertionsOut(availableInsertionsIndex).group_or_chain_id :=
6963 engStApprovers(positionIn - 1).group_or_chain_id;
6964 availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.afterApprover;
6965 availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
6966 availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
6967 availableInsertionsOut(availableInsertionsIndex).authority := engStApprovers(positionIn - 1).authority;
6968 availableInsertionsOut(availableInsertionsIndex).description :=
6969 ame_util.afterApproverDescription || prevApproverDescription;
6970 end if;
6971
6972 if positionIn <= engStApproversCount then
6973
6974 if (engStApprovers(positionIn).authority = ame_util.authorityApprover and
6975 engStApprovers(positionIn).api_insertion <> ame_util.apiInsertion and
6976 engStApprovers(positionIn).approver_category = ame_util.approvalApproverCategory and
6977 coaInsertionsYNIn = ame_util.booleanTrue and
6978 (not ame_engine.insertionExists
6979 (orderTypeIn => ame_util.afterApprover
6980 ,parameterIn => tempParameter
6981 ))) then /* COA */
6982 availableInsertionsIndex := availableInsertionsIndex + 1;
6983 availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn - 1).item_class;
6984 availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn - 1).item_id;
6985 availableInsertionsOut(availableInsertionsIndex).action_type_id :=
6986 engStApprovers(positionIn - 1).action_type_id;
6987 availableInsertionsOut(availableInsertionsIndex).group_or_chain_id :=
6988 engStApprovers(positionIn - 1).group_or_chain_id;
6989 availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.afterApprover;
6990 /* We've already build the parameter field above, let's not repeat the work here. */
6991 availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
6992 availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiAuthorityInsertion;
6993 availableInsertionsOut(availableInsertionsIndex).authority := engStApprovers(positionIn - 1).authority;
6994 availableInsertionsOut(availableInsertionsIndex).description :=
6995 ame_util.afterApproverDescription || prevApproverDescription;
6996 end if;
6997 end if;
6998 end if;
6999 end if;
7000
7001 /*
7002 ORDER TYPE: beforeApprover
7003 beforeApprover is available if engStApproversCount > 0 and positionIn < engStApproversCount + 1.
7004 */
7005 if (orderTypeIn is null or
7006 orderTypeIn = ame_util.beforeApprover
7007 ) then
7008
7009 if (positionIn = engStApproversCount + 1 or
7010 engStApproversCount = 0) then
7011 nextApproverDescription := null;
7012 else
7013 begin
7014 nextApproverDescription :=
7015 ame_approver_type_pkg.getApproverDisplayName(nameIn => engStApprovers(positionIn).name);
7016 exception
7017 when others then
7018 l_error_code := sqlcode;
7019 if l_error_code = -20213 then
7020 errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
7021 messageNameIn => 'AME_400837_INV_APR_FOUND',
7022 tokenNameOneIn => 'PROCESS_NAME',
7023 tokenValueOneIn => 'ame_engine.getInsertions',
7024 tokenNameTwoIn => 'NAME',
7025 tokenValueTwoIn => engStApprovers(positionIn).name);
7026 raise_application_error(errorCode,errorMessage);
7027 end if;
7028 raise;
7029 end;
7030 end if;
7031
7032 if (engStApproversCount > 0 and
7033 positionIn < engStApproversCount + 1) then
7034
7035 tempParameter := engStApprovers(positionIn).name ||
7036 ame_util.fieldDelimiter ||
7037 engStApprovers(positionIn).item_class ||
7038 ame_util.fieldDelimiter ||
7039 engStApprovers(positionIn).item_id ||
7040 ame_util.fieldDelimiter ||
7041 engStApprovers(positionIn).action_type_id ||
7042 ame_util.fieldDelimiter ||
7043 engStApprovers(positionIn).group_or_chain_id ||
7044 ame_util.fieldDelimiter ||
7045 engStApprovers(positionIn).occurrence;
7046
7047 if (not ame_engine.insertionExists
7048 (orderTypeIn => ame_util.beforeApprover
7049 ,parameterIn => tempParameter
7050 )) then
7051 availableInsertionsIndex := availableInsertionsIndex + 1;
7052 availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn).item_class;
7053 availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn).item_id;
7054 availableInsertionsOut(availableInsertionsIndex).action_type_id := engStApprovers(positionIn).action_type_id;
7055 availableInsertionsOut(availableInsertionsIndex).group_or_chain_id :=
7056 engStApprovers(positionIn).group_or_chain_id;
7057 availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.beforeApprover;
7058 availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7059 availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7060 availableInsertionsOut(availableInsertionsIndex).authority := engStApprovers(positionIn).authority;
7061 availableInsertionsOut(availableInsertionsIndex).description :=
7062 ame_util.beforeApproverDescription || nextApproverDescription;
7063 end if;
7064 end if;
7065 end if;
7066
7067 /*
7068 ORDER TYPE: firstAuthority
7069 firstAuthority is available if the approver you're at is the first COA approver in a chain.
7070 */
7071 if (coaInsertionsYNIn = ame_util.booleanTrue and
7072 (orderTypeIn is null or
7073 orderTypeIn = ame_util.firstAuthority)) then
7074
7075 if (positionIn < engStApproversCount + 1 and
7076 engStApprovers(positionIn).authority = ame_util.authorityApprover and
7077 engStApprovers(positionIn).api_insertion <> ame_util.apiInsertion) then
7078 tempBoolean := true; /* tempBoolean remains true if no previous authority is found. */
7079 for i in reverse 1..positionIn - 1 loop
7080 if (engStApprovers(i).group_or_chain_id <> engStApprovers(positionIn).group_or_chain_id or
7081 engStApprovers(i).action_type_id <> engStApprovers(positionIn).action_type_id or
7082 engStApprovers(i).item_id <> engStApprovers(positionIn).item_id or
7083 engStApprovers(i).item_class <> engStApprovers(positionIn).item_class) then
7084 exit;
7085 end if;
7086
7087 if (engStApprovers(i).authority = ame_util.authorityApprover and
7088 engStApprovers(i).api_insertion <> ame_util.apiInsertion) then
7089 tempBoolean := false;
7090 exit;
7091 end if;
7092 end loop;
7093
7094 if (tempBoolean) then
7095 tempParameter := ame_util.firstAuthorityParameter ||
7096 ame_util.fieldDelimiter ||
7097 engStApprovers(positionIn).item_class ||
7098 ame_util.fieldDelimiter ||
7099 engStApprovers(positionIn).item_id ||
7100 ame_util.fieldDelimiter ||
7101 engStApprovers(positionIn).action_type_id ||
7102 ame_util.fieldDelimiter ||
7103 engStApprovers(positionIn).group_or_chain_id;
7104
7105 if (not ame_engine.insertionExists
7106 (orderTypeIn => ame_util.firstAuthority
7107 ,parameterIn => tempParameter
7108 )) then
7109 availableInsertionsIndex := availableInsertionsIndex + 1;
7110 availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn).item_class;
7111 availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn).item_id;
7112 availableInsertionsOut(availableInsertionsIndex).action_type_id :=
7113 engStApprovers(positionIn).action_type_id;
7114 availableInsertionsOut(availableInsertionsIndex).group_or_chain_id :=
7115 engStApprovers(positionIn).group_or_chain_id;
7116 availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.firstAuthority;
7117 availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7118 availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiAuthorityInsertion;
7119 availableInsertionsOut(availableInsertionsIndex).authority := ame_util.authorityApprover;
7120 availableInsertionsOut(availableInsertionsIndex).description := ame_util.firstAuthorityDescription;
7121 end if;
7122 end if;
7123 end if;
7124 end if;
7125
7126 /*
7127 ORDER TYPE: firstPostApprover
7128 Assume that in the case of an entirely empty approver list, we allow insertion of a first
7129 post-approver into the header item's list only. Otherwise, we only allow insertion of a
7130 first post-approver into a non-empty item list. Here is the case analysis:
7131 if(the approver list is empty) then
7132 allow a first-post-approver insertion for the header
7133 elsif(positionIn is after the end of the approver list) then
7134 if(the last approver in the list is not a post-approver) then
7135 allow a first-post-approver insertion for the last approver's item
7136 end if
7137 elsif(positionIn = 1) then
7138 if(the first approver in the list is a post-approver_ then
7139 allow a first-post-approver insertion for the first approver's item
7140 end if
7141 else
7142 if(the engStApprovers at positionIn - 1 and positionIn are for the same item) then
7143 if(the first approver is not a post-approver and
7144 the second approver is a post-approver) then
7145 allow a first-post-approver insertion for the engStApprovers' item
7146 end if
7147 else
7148 if(the second approver is a post-approver) then
7149 allow a first-post-approver insertion for the second approver's item
7150 end if
7151 if(the first approver is not a post-approver) then
7152 allow a first-post-approver insertion for the first approver's item
7153 end if
7154 end if
7155 end if
7156 */
7157 if (orderTypeIn is null or
7158 orderTypeIn = ame_util.firstPostApprover) then
7159
7160 if (engStApproversCount = 0) then
7161 tempParameter := ame_util.firstPostParameter ||
7162 ame_util.fieldDelimiter ||
7163 ame_util.headerItemClassName ||
7164 ame_util.fieldDelimiter ||
7165 engTransactionId;
7166
7167 if (not ame_engine.insertionExists
7168 (orderTypeIn => ame_util.firstPostApprover
7169 ,parameterIn => tempParameter
7170 )) then
7171 availableInsertionsIndex := availableInsertionsIndex + 1;
7172 availableInsertionsOut(availableInsertionsIndex).item_class := ame_util.headerItemClassName;
7173 availableInsertionsOut(availableInsertionsIndex).item_id := engTransactionId;
7174 availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7175 availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7176 availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.firstPostApprover;
7177 availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7178 availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7179 availableInsertionsOut(availableInsertionsIndex).authority := ame_util.postApprover;
7180 availableInsertionsOut(availableInsertionsIndex).description := ame_util.firstPostApproverDescription;
7181 end if;
7182 elsif (positionIn = engStApproversCount + 1) then
7183 if (engStApprovers(engStApproversCount).authority <> ame_util.postApprover) then
7184 tempParameter := ame_util.firstPostParameter ||
7185 ame_util.fieldDelimiter ||
7186 engStApprovers(engStApproversCount).item_class ||
7187 ame_util.fieldDelimiter ||
7188 engStApprovers(engStApproversCount).item_id;
7189 if (not ame_engine.insertionExists
7190 (orderTypeIn => ame_util.firstPostApprover
7191 ,parameterIn => tempParameter
7192 )) then
7193 availableInsertionsIndex := availableInsertionsIndex + 1;
7194 availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(engStApproversCount).item_class;
7195 availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(engStApproversCount).item_id;
7196 availableInsertionsOut(availableInsertionsIndex).action_type_id :=
7197 ame_util.nullInsertionActionTypeId;
7198 availableInsertionsOut(availableInsertionsIndex).group_or_chain_id :=
7199 ame_util.nullInsertionGroupOrChainId;
7200 availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.firstPostApprover;
7201 availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7202 availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7203 availableInsertionsOut(availableInsertionsIndex).authority := ame_util.postApprover;
7204 availableInsertionsOut(availableInsertionsIndex).description := ame_util.firstPostApproverDescription;
7205 end if;
7206 end if;
7207 elsif (positionIn = 1) then
7208 if (engStApprovers(1).authority = ame_util.postApprover) then
7209 tempParameter := ame_util.firstPostParameter ||
7210 ame_util.fieldDelimiter ||
7211 engStApprovers(1).item_class ||
7212 ame_util.fieldDelimiter ||
7213 engStApprovers(1).item_id;
7214 if (not ame_engine.insertionExists
7215 (orderTypeIn => ame_util.firstPostApprover
7216 ,parameterIn => tempParameter
7217 )) then
7218 availableInsertionsIndex := availableInsertionsIndex + 1;
7219 availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(1).item_class;
7220 availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(1).item_id;
7221 availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7222 availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7223 availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.firstPostApprover;
7224 availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7225 availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7226 availableInsertionsOut(availableInsertionsIndex).authority := ame_util.postApprover;
7227 availableInsertionsOut(availableInsertionsIndex).description := ame_util.firstPostApproverDescription;
7228 end if;
7229 end if;
7230 else
7231 if (engStApprovers(positionIn - 1).item_id = engStApprovers(positionIn).item_id and
7232 engStApprovers(positionIn - 1).item_class = engStApprovers(positionIn).item_class) then
7233 if (engStApprovers(positionIn - 1).authority <> ame_util.postApprover and
7234 engStApprovers(positionIn).authority = ame_util.postApprover) then
7235 tempParameter := ame_util.firstPostParameter ||
7236 ame_util.fieldDelimiter ||
7237 engStApprovers(positionIn).item_class ||
7238 ame_util.fieldDelimiter ||
7239 engStApprovers(positionIn).item_id;
7240 if (not ame_engine.insertionExists
7241 (orderTypeIn => ame_util.firstPostApprover
7242 ,parameterIn => tempParameter
7243 )) then
7244 availableInsertionsIndex := availableInsertionsIndex + 1;
7245 availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn).item_class;
7246 availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn).item_id;
7247 availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7248 availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7249 availableInsertionsOut(availableInsertionsIndex).group_or_chain_id :=
7250 engStApprovers(positionIn).group_or_chain_id;
7251 availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.firstPostApprover;
7252 availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7253 availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7254 availableInsertionsOut(availableInsertionsIndex).authority := ame_util.postApprover;
7255 availableInsertionsOut(availableInsertionsIndex).description := ame_util.firstPostApproverDescription;
7256 end if;
7257 end if;
7258 else
7259 if (engStApprovers(positionIn).authority = ame_util.postApprover) then
7260 tempParameter := ame_util.firstPostParameter ||
7261 ame_util.fieldDelimiter ||
7262 engStApprovers(positionIn).item_class ||
7263 ame_util.fieldDelimiter ||
7264 engStApprovers(positionIn).item_id;
7265 if (not ame_engine.insertionExists
7266 (orderTypeIn => ame_util.firstPostApprover
7267 ,parameterIn => tempParameter
7268 )) then
7269 availableInsertionsIndex := availableInsertionsIndex + 1;
7270 availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn).item_class;
7271 availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn).item_id;
7272 availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7273 availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7274 availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.firstPostApprover;
7275 availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7276 availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7277 availableInsertionsOut(availableInsertionsIndex).authority := ame_util.postApprover;
7278 availableInsertionsOut(availableInsertionsIndex).description := ame_util.firstPostApproverDescription;
7279 end if;
7280 end if;
7281
7282 if (engStApprovers(positionIn - 1).authority <> ame_util.postApprover) then
7283 tempParameter := ame_util.firstPostParameter ||
7284 ame_util.fieldDelimiter ||
7285 engStApprovers(positionIn - 1).item_class ||
7286 ame_util.fieldDelimiter ||
7287 engStApprovers(positionIn - 1).item_id;
7288 if (not ame_engine.insertionExists
7289 (orderTypeIn => ame_util.firstPostApprover
7290 ,parameterIn => tempParameter
7291 )) then
7292 availableInsertionsIndex := availableInsertionsIndex + 1;
7293 availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn - 1).item_class;
7294 availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn - 1).item_id;
7295 availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7296 availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7297 availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.firstPostApprover;
7298 availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7299 availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7300 availableInsertionsOut(availableInsertionsIndex).authority := ame_util.postApprover;
7301 availableInsertionsOut(availableInsertionsIndex).description := ame_util.firstPostApproverDescription;
7302 end if;
7303 end if;
7304 end if;
7305 end if;
7306 end if;
7307
7308 /*
7309 ORDER TYPE: firstPreApprover
7310 Assume that in the case of an entirely empty approver list, we allow insertion of a first
7311 pre-approver into the header item's list only. Otherwise, we only allow insertion of a
7312 first pre-approver into a non-empty item list. Here is the case analysis:
7313 if(the approver list is empty) then
7314 allow a first-pre-approver insertion for the header item
7315 elsif(positionIn = 1) then
7316 allow a first-pre-approver insertion for the first approver's item
7317 elsif(positionIn < engStApproversCount + 1) then
7318 if(the engStApprovers at positionIn - 1 and positionIn are for different items) then
7319 allow a first-pre-approver insertion for the second approver's item
7320 end if
7321 end if
7322 */
7323 if (orderTypeIn is null or
7324 orderTypeIn = ame_util.firstPreApprover) then
7325
7326 if (engStApproversCount = 0) then
7327 tempParameter := ame_util.firstPreApprover ||
7328 ame_util.fieldDelimiter ||
7329 ame_util.headerItemClassName ||
7330 ame_util.fieldDelimiter ||
7331 engTransactionId;
7332 if (not ame_engine.insertionExists
7333 (orderTypeIn => ame_util.firstPreApprover
7334 ,parameterIn => tempParameter
7335 )) then
7336 availableInsertionsIndex := availableInsertionsIndex + 1;
7337 availableInsertionsOut(availableInsertionsIndex).item_class := ame_util.headerItemClassName;
7338 availableInsertionsOut(availableInsertionsIndex).item_id := engTransactionId;
7339 availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7340 availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7341 availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.firstPreApprover;
7342 availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7343 availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7344 availableInsertionsOut(availableInsertionsIndex).authority := ame_util.preApprover;
7345 availableInsertionsOut(availableInsertionsIndex).description := ame_util.firstPreApproverDescription;
7346 end if;
7347 elsif (positionIn = 1) then
7348 tempParameter := ame_util.firstPreApprover ||
7349 ame_util.fieldDelimiter ||
7350 engStApprovers(1).item_class ||
7351 ame_util.fieldDelimiter ||
7352 engStApprovers(1).item_id;
7353 if (not ame_engine.insertionExists
7354 (orderTypeIn => ame_util.firstPreApprover
7355 ,parameterIn => tempParameter
7356 )) then
7357 availableInsertionsIndex := availableInsertionsIndex + 1;
7358 availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(1).item_class;
7359 availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(1).item_id;
7360 availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7361 availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7362 availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.firstPreApprover;
7363 availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7364 availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7365 availableInsertionsOut(availableInsertionsIndex).authority := ame_util.preApprover;
7366 availableInsertionsOut(availableInsertionsIndex).description := ame_util.firstPreApproverDescription;
7367 end if;
7368 elsif (positionIn < engStApproversCount + 1) then
7369 if (engStApprovers(positionIn - 1).item_id <> engStApprovers(positionIn).item_id or
7370 engStApprovers(positionIn - 1).item_class <> engStApprovers(positionIn).item_class) then
7371 tempParameter := ame_util.firstPreApprover ||
7372 ame_util.fieldDelimiter ||
7373 engStApprovers(positionIn).item_class ||
7374 ame_util.fieldDelimiter ||
7375 engStApprovers(positionIn).item_id;
7376 if (not ame_engine.insertionExists
7377 (orderTypeIn => ame_util.firstPreApprover
7378 ,parameterIn => tempParameter
7379 )) then
7380 availableInsertionsIndex := availableInsertionsIndex + 1;
7381 availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn).item_class;
7382 availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn).item_id;
7383 availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7384 availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7385 availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.firstPreApprover;
7386 availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7387 availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7388 availableInsertionsOut(availableInsertionsIndex).authority := ame_util.preApprover;
7389 availableInsertionsOut(availableInsertionsIndex).description := ame_util.firstPreApproverDescription;
7390 end if;
7391 end if;
7392 end if;
7393 end if;
7394
7395 /*
7396 ORDER TYPE: lastPostApprover
7397 Assume that in the case of an entirely empty approver list, we allow insertion of a last
7398 post-approver into the header item's list only. Otherwise, we only allow insertion of a
7399 last post-approver into a non-empty item list. Here is the case analysis:
7400 if(the approver list is empty) then
7401 allow last-post-approver insertion for the header item
7402 elsif(positionIn = engStApproversCount + 1) then
7403 allow last-post-approver insertion for the last approver's item
7404 elsif(positionIn > 1) then
7405 if(the engStApprovers at positionIn - 1 and positionIn are for different items) then
7406 allow last-post-approver insertion for the former approver's item
7407 end if
7408 end if
7409 */
7410 if (orderTypeIn is null or
7411 orderTypeIn = ame_util.lastPostApprover) then
7412 if (engStApproversCount = 0) then
7413 tempParameter := ame_util.lastPostApprover ||
7414 ame_util.fieldDelimiter ||
7415 ame_util.headerItemClassName ||
7416 ame_util.fieldDelimiter ||
7417 engTransactionId;
7418 if (not ame_engine.insertionExists
7419 (orderTypeIn => ame_util.lastPostApprover
7420 ,parameterIn => tempParameter
7421 )) then
7422 availableInsertionsIndex := availableInsertionsIndex + 1;
7423 availableInsertionsOut(availableInsertionsIndex).item_class := ame_util.headerItemClassName;
7424 availableInsertionsOut(availableInsertionsIndex).item_id := engTransactionId;
7425 availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7426 availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7427 availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.lastPostApprover;
7428 availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7429 availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7430 availableInsertionsOut(availableInsertionsIndex).authority := ame_util.postApprover;
7431 availableInsertionsOut(availableInsertionsIndex).description := ame_util.lastPostApproverDescription;
7432 end if;
7433 elsif (positionIn = engStApproversCount + 1) then
7434 tempParameter := ame_util.lastPostApprover ||
7435 ame_util.fieldDelimiter ||
7436 engStApprovers(engStApproversCount).item_class ||
7437 ame_util.fieldDelimiter ||
7438 engStApprovers(engStApproversCount).item_id;
7439 if (not ame_engine.insertionExists
7440 (orderTypeIn => ame_util.lastPostApprover
7441 ,parameterIn => tempParameter
7442 )) then
7443 availableInsertionsIndex := availableInsertionsIndex + 1;
7444 availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(engStApproversCount).item_class;
7445 availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(engStApproversCount).item_id;
7446 availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7447 availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7448 availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.lastPostApprover;
7449 availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7450 availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7451 availableInsertionsOut(availableInsertionsIndex).authority := ame_util.postApprover;
7452 availableInsertionsOut(availableInsertionsIndex).description := ame_util.lastPostApproverDescription;
7453 end if;
7454 elsif (positionIn > 1) then
7455 if (engStApprovers(positionIn - 1).item_id <> engStApprovers(positionIn).item_id or
7456 engStApprovers(positionIn - 1).item_class <> engStApprovers(positionIn).item_class) then
7457 tempParameter := ame_util.lastPostApprover ||
7458 ame_util.fieldDelimiter ||
7459 engStApprovers(positionIn - 1).item_class ||
7460 ame_util.fieldDelimiter ||
7461 engStApprovers(positionIn - 1).item_id;
7462 if (not ame_engine.insertionExists
7463 (orderTypeIn => ame_util.lastPostApprover
7464 ,parameterIn => tempParameter
7465 )) then
7466 availableInsertionsIndex := availableInsertionsIndex + 1;
7467 availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn - 1).item_class;
7468 availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn - 1).item_id;
7469 availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7470 availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7471 availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.lastPostApprover;
7472 availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7473 availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7474 availableInsertionsOut(availableInsertionsIndex).authority := ame_util.postApprover;
7475 availableInsertionsOut(availableInsertionsIndex).description := ame_util.lastPostApproverDescription;
7476 end if;
7477 end if;
7478 end if;
7479 end if;
7480
7481 /*
7482 ORDER TYPE: lastPreApprover
7483 Assume that in the case of an entirely empty approver list, we allow insertion of a last
7484 pre-approver into the header item's list only. Otherwise, we only allow insertion of a
7485 last pre-approver into a non-empty item list. Here is the case analysis:
7486 if(the approver list is empty) then
7487 allow last-pre-approver insertion for the header item
7488 elsif(positionIn = 1) then
7489 if(the approver at position 1 is not a pre-approver) then
7490 allow last-pre-approver insertion for the item of the first approver
7491 end if
7492 elsif(positionIn <= engStApproversCount) then
7493 if(the engStApprovers at positionIn - 1 and positionIn are for the same item) then
7494 if(the approver at positionIn - 1 is a pre-approver and
7495 the approver at positionIn is not a pre-approver) then
7496 allow last-pre-approver insertion for the engStApprovers' item
7497 end if
7498 else
7499 if(the approver at positionIn is not a pre-approver) then
7500 allow last-pre-approver insertion for the item of the approver at positionIn
7501 end if
7502 end if
7503 end if
7504 */
7505 if (orderTypeIn is null or
7506 orderTypeIn = ame_util.lastPreApprover) then
7507 if (engStApproversCount = 0) then
7508 tempParameter := ame_util.lastPreApprover ||
7509 ame_util.fieldDelimiter ||
7510 ame_util.headerItemClassName ||
7511 ame_util.fieldDelimiter ||
7512 engTransactionId;
7513 if (not ame_engine.insertionExists
7514 (orderTypeIn => ame_util.lastPreApprover
7515 ,parameterIn => tempParameter)) then
7516 availableInsertionsIndex := availableInsertionsIndex + 1;
7517 availableInsertionsOut(availableInsertionsIndex).item_class := ame_util.headerItemClassName;
7518 availableInsertionsOut(availableInsertionsIndex).item_id := engTransactionId;
7519 availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7520 availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7521 availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.lastPreApprover;
7522 availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7523 availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7524 availableInsertionsOut(availableInsertionsIndex).authority := ame_util.preApprover;
7525 availableInsertionsOut(availableInsertionsIndex).description := ame_util.lastPreApproverDescription;
7526 end if;
7527 elsif (positionIn = 1) then
7528 if (engStApprovers(1).authority <> ame_util.preApprover) then
7529 tempParameter := ame_util.lastPreApprover ||
7530 ame_util.fieldDelimiter ||
7531 engStApprovers(1).item_class ||
7532 ame_util.fieldDelimiter ||
7533 engStApprovers(1).item_id;
7534 if (not ame_engine.insertionExists
7535 (orderTypeIn => ame_util.lastPreApprover
7536 ,parameterIn => tempParameter
7537 )) then
7538 availableInsertionsIndex := availableInsertionsIndex + 1;
7539 availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(1).item_class;
7540 availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(1).item_id;
7541 availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7542 availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7543 availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.lastPreApprover;
7544 availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7545 availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7546 availableInsertionsOut(availableInsertionsIndex).authority := ame_util.preApprover;
7547 availableInsertionsOut(availableInsertionsIndex).description := ame_util.lastPreApproverDescription;
7548 end if;
7549 end if;
7550 elsif (positionIn <= engStApproversCount) then
7551 if (engStApprovers(positionIn - 1).item_id = engStApprovers(positionIn).item_id and
7552 engStApprovers(positionIn - 1).item_class = engStApprovers(positionIn).item_class) then
7553 if (engStApprovers(positionIn - 1).authority = ame_util.preApprover and
7554 engStApprovers(positionIn).authority <> ame_util.preApprover) then
7555 tempParameter := ame_util.lastPreApprover ||
7556 ame_util.fieldDelimiter ||
7557 engStApprovers(positionIn).item_class ||
7558 ame_util.fieldDelimiter ||
7559 engStApprovers(positionIn).item_id;
7560 if (not ame_engine.insertionExists
7561 (orderTypeIn => ame_util.lastPreApprover
7562 ,parameterIn => tempParameter
7563 )) then
7564 availableInsertionsIndex := availableInsertionsIndex + 1;
7565 availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn).item_class;
7566 availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn).item_id;
7567 availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7568 availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7569 availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.lastPreApprover;
7570 availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7571 availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7572 availableInsertionsOut(availableInsertionsIndex).authority := ame_util.preApprover;
7573 availableInsertionsOut(availableInsertionsIndex).description := ame_util.lastPreApproverDescription;
7574 end if;
7575 end if;
7576 else
7577 if (engStApprovers(positionIn).authority <> ame_util.preApprover) then
7578 tempParameter := ame_util.lastPreApprover ||
7579 ame_util.fieldDelimiter ||
7580 engStApprovers(positionIn).item_class ||
7581 ame_util.fieldDelimiter ||
7582 engStApprovers(positionIn).item_id;
7583 if (not ame_engine.insertionExists
7584 (orderTypeIn => ame_util.lastPreApprover
7585 ,parameterIn => tempParameter
7586 )) then
7587 availableInsertionsIndex := availableInsertionsIndex + 1;
7588 availableInsertionsOut(availableInsertionsIndex).item_class := engStApprovers(positionIn).item_class;
7589 availableInsertionsOut(availableInsertionsIndex).item_id := engStApprovers(positionIn).item_id;
7590 availableInsertionsOut(availableInsertionsIndex).action_type_id := ame_util.nullInsertionActionTypeId;
7591 availableInsertionsOut(availableInsertionsIndex).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
7592 availableInsertionsOut(availableInsertionsIndex).order_type := ame_util.lastPreApprover;
7593 availableInsertionsOut(availableInsertionsIndex).parameter := tempParameter;
7594 availableInsertionsOut(availableInsertionsIndex).api_insertion := ame_util.apiInsertion;
7595 availableInsertionsOut(availableInsertionsIndex).authority := ame_util.preApprover;
7596 availableInsertionsOut(availableInsertionsIndex).description := ame_util.lastPreApproverDescription;
7597 end if;
7598 end if;
7599 end if;
7600 end if;
7601 end if;
7602
7603 exception
7604 when invalidPositionException then
7605 errorCode := -20211;
7606 errorMessage := ame_util.getMessage
7607 (applicationShortNameIn =>'PER'
7608 ,messageNameIn => 'AME_400418_INVALID_INSERTION'
7609 );
7610 ame_util.runtimeException
7611 (packageNameIn => 'ame_engine'
7612 ,routineNameIn => 'getInsertions'
7613 ,exceptionNumberIn => errorCode
7614 ,exceptionStringIn => errorMessage
7615 );
7616 raise_application_error(errorCode,errorMessage);
7617
7618 when others then
7619 ame_util.runtimeException
7620 (packageNameIn => 'ame_engine'
7621 ,routineNameIn => 'getInsertions'
7622 ,exceptionNumberIn => sqlcode
7623 ,exceptionStringIn => sqlerrm
7624 );
7625 raise;
7626 end getInsertions;
7627 procedure getLMCondition(ruleIdIn in integer,
7628 parameterOneOut out nocopy varchar2,
7629 parameterTwoOut out nocopy varchar2) as
7630 errorCode integer;
7631 errorMessage ame_util.longestStringType;
7632 invalidNameException exception;
7633 tempRuleKey ame_rules.rule_key%type;
7634 parameterOne ame_conditions.parameter_one%type;
7635 parameterTwo ame_conditions.parameter_two%type;
7636 begin
7637 /* Checked for cached values. */
7638 if(not engLMParameterOnes.exists(ruleIdIn)) then
7639 /* Select the values, as they were not cached. */
7640 select
7641 ame_conditions.parameter_one,
7642 ame_conditions.parameter_two
7643 into
7644 parameterOne,
7645 parameterTwo
7646 from
7647 ame_conditions,
7648 ame_condition_usages
7649 where
7650 ame_condition_usages.rule_id = ruleIdIn and
7651 ame_condition_usages.condition_id = ame_conditions.condition_id and
7652 ame_conditions.condition_type = ame_util.listModConditionType and
7653 engEffectiveRuleDate between
7654 ame_conditions.start_date and
7655 nvl(ame_conditions.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
7656 engEffectiveRuleDate between
7657 ame_condition_usages.start_date and
7658 nvl(ame_condition_usages.end_date - ame_util.oneSecond, engEffectiveRuleDate) and
7659 rownum < 2; /* Avoids second fetch otherwise required by ANSI standard to check for too many rows. */
7660 /* Check for an invalid wf_roles.name value in parameter_two. */
7661 if(parameterTwo = ame_util.invalidApproverWfRolesName) then
7662 raise invalidNameException;
7663 end if;
7664 /* Cache the values. */
7665 engLMParameterOnes(ruleIdIn) := parameterOne;
7666 engLMParameterTwos(ruleIdIn) := parameterTwo;
7667 end if;
7668 /* Return the values. */
7669 parameterOneOut := engLMParameterOnes(ruleIdIn);
7670 parameterTwoOut := engLMParameterTwos(ruleIdIn);
7671 exception
7672 when invalidNameException then
7673 tempRuleKey := ame_rule_pkg.getRuleKey(ruleIdIn => ruleIdIn);
7674 errorCode := -20001;
7675 errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
7676 messageNameIn => 'AME_400685_INV_LM_RULE',
7677 tokenNameOneIn => 'RULE_KEY',
7678 tokenValueOneIn => tempRuleKey);
7679 ame_util.runtimeException(packageNameIn => 'ame_engine',
7680 routineNameIn => 'getLMCondition',
7681 exceptionNumberIn => errorCode,
7682 exceptionStringIn => errorMessage);
7683 raise_application_error(errorCode,
7684 errorMessage);
7685 when others then
7686 ame_util.runtimeException(packageNameIn => 'ame_engine',
7687 routineNameIn => 'getLMCondition',
7688 exceptionNumberIn => sqlcode,
7689 exceptionStringIn => sqlerrm);
7690 raise;
7691 end getLMCondition;
7692 procedure getNextApprovers(
7693 applicationIdIn in number
7694 ,transactionTypeIn in varchar2
7695 ,transactionIdIn in varchar2
7696 ,nextApproversType in number
7697 ,flagApproversAsNotifiedIn in varchar2 default ame_util.booleanTrue
7698 ,approvalProcessCompleteYNOut out nocopy varchar2
7699 ,nextApproversOut out nocopy ame_util.approversTable2
7700 ,itemIndexesOut out nocopy ame_util.idList
7701 ,itemClassesOut out nocopy ame_util.stringList
7702 ,itemIdsOut out nocopy ame_util.stringList
7703 ,itemSourcesOut out nocopy ame_util.longStringList
7704 ,productionIndexesOut out nocopy ame_util.idList
7705 ,variableNamesOut out nocopy ame_util.stringList
7706 ,variableValuesOut out nocopy ame_util.stringList
7707 ,transVariableNamesOut out nocopy ame_util.stringList
7708 ,transVariableValuesOut out nocopy ame_util.stringList) as
7709 allItemsNotSuspended boolean;
7710 ameApplicationId integer;
7711 copyAncillaryData boolean;
7712 nextApproverCount integer;
7713 nextTreeNodeIndex integer;
7714 tempTreeNodeIndex integer;
7715 approverItemCount integer;
7716 approverProdCount integer;
7717 currentTreeNode ame_util.approverTreeRecord;
7718 evaluateNextNode boolean;
7719 currentOrderNumber integer;
7720 nextApproverTreeIndexList ame_util.idList;
7721 currentApproverIndex integer;
7722 tempApproverIndexes ame_util.idList;
7723 -- tempItemClass ame_util.stringType;
7724 -- tempItemId ame_util.stringType;
7725 processSibling boolean;
7726 tempTreeNode ame_util.approverTreeRecord;
7727 -- following two variables added - to use incase of item_class is null
7728 tempItemClass ame_util.stringType;
7729 tempItemId ame_util.stringType;
7730 -- repeated
7731 tempRepeatedCount integer;
7732 tempRepeatedCount2 integer;
7733 tempPrepareItemData boolean := true;
7734 tempProcessProductionActions boolean := false;
7735 tempProcessProductionRules boolean := false;
7736 tempTreeLevelId integer;
7737 --+
7738 previousNodeOrderNumber integer;
7739 previousTreeLevelId varchar2(320);
7740 previousNodeStatus integer;
7741 --+
7742 prevApproverOrderNumber integer;
7743 prevApproverName varchar2(320);
7744 prevApproverStatus integer;
7745 --+
7746 begin
7747 if nextApproversType = 4 then
7748 tempPrepareItemData := false;
7749 end if;
7750 if nextApproversType = 2 or nextApproversType = 3 then
7751 tempProcessProductionActions := true;
7752 end if;
7753 if nextApproversType = 3 then
7754 tempProcessProductionRules := true;
7755 end if;
7756 ame_engine.lockTransaction(fndApplicationIdIn => applicationIdIn,
7757 transactionIdIn => transactionIdIn,
7758 transactionTypeIdIn => transactionTypeIn);
7759 ame_engine.updateTransactionState(isTestTransactionIn => false
7760 ,isLocalTransactionIn => false
7761 ,fetchConfigVarsIn => true
7762 ,fetchOldApproversIn => true
7763 ,fetchInsertionsIn => true
7764 ,fetchDeletionsIn => true
7765 ,fetchAttributeValuesIn => true
7766 ,fetchInactiveAttValuesIn => false
7767 ,processProductionActionsIn => tempProcessProductionActions
7768 ,processProductionRulesIn => tempProcessProductionRules
7769 ,updateCurrentApproverListIn => true
7770 ,updateOldApproverListIn => true
7771 ,processPrioritiesIn => true
7772 ,prepareItemDataIn => tempPrepareItemData
7773 ,prepareRuleIdsIn => false
7774 ,prepareRuleDescsIn => false
7775 ,prepareApproverTreeIn => true
7776 ,transactionIdIn => transactionIdIn
7777 ,ameApplicationIdIn => null
7778 ,fndApplicationIdIn => applicationIdIn
7779 ,transactionTypeIdIn => transactionTypeIn);
7780 approvalProcessCompleteYNOut := ame_engine.getApprovalProcessCompleteYN;
7781 ameApplicationId := ame_engine.getAmeApplicationId;
7782 /* If approvalProcessCompleteYNOut is 'Y', there should be no nextApprovers. Hence
7783 return with an empty nextApproversOut table */
7784 if approvalProcessCompleteYNOut = ame_util2.completeFullyApproved or
7785 approvalProcessCompleteYNOut = ame_util2.completeFullyRejected or
7786 approvalProcessCompleteYNOut = ame_util2.completePartiallyApproved or
7787 approvalProcessCompleteYNOut = ame_util2.completeNoApprovers then
7788 ame_engine.unlockTransaction(fndApplicationIdIn => applicationIdIn,
7789 transactionIdIn => transactionIdIn,
7790 transactionTypeIdIn => transactionTypeIn);
7791 return;
7792 end if;
7793 copyAncillaryData := false;
7794 nextApproverCount := 0; /* Pre increment */
7795 approverItemCount := 0;
7796 approverProdCount := 0;
7797 nextTreeNodeIndex := 1;
7798 evaluateNextNode := true;
7799 currentOrderNumber := null;
7800 processSibling := true;
7801 loop
7802 currentTreeNode := engStApproversTree(nextTreeNodeIndex);
7803 if currentTreeNode.is_suspended is null or
7804 currentTreeNode.is_suspended = ame_util.booleanFalse then
7805 if currentTreeNode.tree_level = 6 and
7806 (currentTreeNode.status = ame_util.startedStatus
7807 and engStApprovers(currentTreeNode.approver_index).approval_status
7808 <> ame_util.notifiedByRepeatedStatus)and
7809 (currentTreeNode.sibling_index <> ame_util.noSiblingIndex
7810 and currentTreeNode.min_order <> engStApproversTree(currentTreeNode.sibling_index).min_order ) then
7811 evaluateNextNode := false;
7812 end if;
7813 if evaluateNextNode then
7814 if currentTreeNode.status <> ame_util.completedStatus then
7815 if currentTreeNode.approver_index = ame_util.noApproverIndex and
7816 evaluateNextNode then
7817 currentOrderNumber := currentTreeNode.min_order;
7818 end if;
7819 else
7820 currentOrderNumber := null;
7821 end if;
7822 if currentTreeNode.approver_index <> ame_util.noApproverIndex
7823 and currentOrderNumber is not null
7824 and currentTreeNode.status = ame_util.notStartedStatus
7825 and currentTreeNode.min_order = currentOrderNumber
7826 and (engStApprovers(currentTreeNode.approver_index).approval_status is null
7827 or engStApprovers(currentTreeNode.approver_index).approval_status
7828 <> ame_util.notifiedByRepeatedStatus)
7829 then
7830 nextApproverCount := nextApproverCount + 1;
7831 ame_util.copyApproverRecord2
7832 (approverRecord2In => engStApprovers(currentTreeNode.approver_index)
7833 ,approverRecord2Out => nextApproversOut(nextApproverCount));
7834 if flagApproversAsNotifiedIn = ame_util.booleanTrue then
7835 setInsertedApprovalStatus(currentApproverIndexIn => currentTreeNode.approver_index
7836 ,approvalStatusIn => ame_util.notifiedStatus );
7837 end if;
7838 currentApproverIndex := currentTreeNode.approver_index;
7839 copyAncillaryData := true;
7840 nextApproverTreeIndexList(nextApproverCount) := nextTreeNodeIndex;
7841 tempApproverIndexes(nextApproverCount) := currentTreeNode.approver_index;
7842 if currentTreeNode.sibling_index <> -1
7843 and currentTreeNode.max_order <> engStApproversTree(currentTreeNode.sibling_index).max_order then
7844 processSibling := false;
7845 else
7846 processSibling := true;
7847 end if;
7848 for x in 1 .. engStRepeatedIndexes.count loop
7849 if engStRepeatedIndexes(x) = currentTreeNode.approver_index
7850 and engStRepeatedAppIndexes(x) <> currentTreeNode.approver_index then
7851 --+
7852 update ame_temp_old_approver_lists
7853 set approval_status = ame_util.notifiedByRepeatedStatus
7854 where application_id = ameApplicationId
7855 and transaction_id = transactionIdIn
7856 and name = engStApprovers(engStRepeatedAppIndexes(x)).name --nextApproversOut(i).name
7857 and item_class = engStApprovers(engStRepeatedAppIndexes(x)).item_class
7858 and item_id = engStApprovers(engStRepeatedAppIndexes(x)).item_id
7859 and action_type_id = engStApprovers(engStRepeatedAppIndexes(x)).action_type_id
7860 and group_or_chain_id = engStApprovers(engStRepeatedAppIndexes(x)).group_or_chain_id
7861 and occurrence = engStApprovers(engStRepeatedAppIndexes(x)).occurrence
7862 and (approval_status is null or approval_status = ame_util.repeatedStatus);
7863 engStApprovers(engStRepeatedAppIndexes(x)).approval_status := ame_util.notifiedByRepeatedStatus;
7864 setInsertedApprovalStatus(currentApproverIndexIn => engStRepeatedAppIndexes(x)
7865 ,approvalStatusIn => ame_util.notifiedByRepeatedStatus);
7866 --+
7867 end if;
7868 end loop;
7869 end if;
7870 if currentOrderNumber is null and currentTreeNode.tree_level = 6 then
7871 if currentTreeNode.approver_index <> ame_util.noApproverIndex and
7872 (currentTreeNode.status = ame_util.completedStatus or
7873 (
7874 currentTreeNode.status = ame_util.startedStatus
7875 and engStApprovers(currentTreeNode.approver_index).approval_status <> ame_util.notifiedByRepeatedStatus
7876 and processSibling
7877 )or
7878 (
7879 currentTreeNode.status = ame_util.notStartedStatus and
7880 currentTreeNode.sibling_index <> ame_util.noSiblingIndex
7881 and currentTreeNode.min_order = engStApproversTree(currentTreeNode.sibling_index).min_order
7882 )
7883 )and
7884 processSibling and --evaluateNextNode and
7885 (currentTreeNode.sibling_index <> ame_util.noSiblingIndex
7886 and engStApproversTree(currentTreeNode.sibling_index).status = ame_util.notStartedStatus
7887 and ( engStApprovers(engStApproversTree(currentTreeNode.sibling_index).approver_index).approval_status is null
7888 or engStApprovers(engStApproversTree(currentTreeNode.sibling_index).approver_index).approval_status
7889 <> ame_util.notifiedByRepeatedStatus)
7890 ) then
7891 --+
7892 if prevApproverOrderNumber is null or
7893 (prevApproverOrderNumber < engStApproversTree(currentTreeNode.sibling_index).min_order
7894 and prevApproverStatus = ame_util.completedStatus) or
7895 (prevApproverOrderNumber = engStApproversTree(currentTreeNode.sibling_index).min_order )
7896 then
7897
7898 nextApproverCount := nextApproverCount + 1;
7899 ame_util.copyApproverRecord2
7900 (approverRecord2In => engStApprovers(engStApproversTree(currentTreeNode.sibling_index).approver_index)
7901 ,approverRecord2Out => nextApproversOut(nextApproverCount));
7902 if flagApproversAsNotifiedIn = ame_util.booleanTrue then
7903 setInsertedApprovalStatus(currentApproverIndexIn => engStApproversTree(currentTreeNode.sibling_index).approver_index
7904 ,approvalStatusIn =>ame_util.notifiedStatus );
7905 end if;
7906 nextApproverTreeIndexList(nextApproverCount) := currentTreeNode.sibling_index;
7907 tempApproverIndexes(nextApproverCount) := engStApproversTree(currentTreeNode.sibling_index).approver_index;
7908 currentApproverIndex := engStApproversTree(currentTreeNode.sibling_index).approver_index;
7909 copyAncillaryData := true;
7910 tempTreeNode := engStApproversTree(currentTreeNode.sibling_index);
7911 if tempTreeNode.sibling_index <> -1
7912 and tempTreeNode.max_order <> engStApproversTree(tempTreeNode.sibling_index).max_order then
7913 processSibling := false;
7914 else
7915 processSibling := true;
7916 end if;
7917 for x in 1 .. engStRepeatedIndexes.count loop
7918 if engStRepeatedIndexes(x) = engStApproversTree(currentTreeNode.sibling_index).approver_index
7919 and engStRepeatedAppIndexes(x) <> engStApproversTree(currentTreeNode.sibling_index).approver_index then
7920 --+
7921 update ame_temp_old_approver_lists
7922 set approval_status = ame_util.notifiedByRepeatedStatus
7923 where application_id = ameApplicationId
7924 and transaction_id = transactionIdIn
7925 and name = engStApprovers(engStRepeatedAppIndexes(x)).name --nextApproversOut(i).name
7926 and item_class = engStApprovers(engStRepeatedAppIndexes(x)).item_class
7927 and item_id = engStApprovers(engStRepeatedAppIndexes(x)).item_id
7928 and action_type_id = engStApprovers(engStRepeatedAppIndexes(x)).action_type_id
7929 and group_or_chain_id = engStApprovers(engStRepeatedAppIndexes(x)).group_or_chain_id
7930 and occurrence = engStApprovers(engStRepeatedAppIndexes(x)).occurrence
7931 and (approval_status is null or approval_status = ame_util.repeatedStatus);
7932 engStApprovers(engStRepeatedAppIndexes(x)).approval_status := ame_util.notifiedByRepeatedStatus;
7933 setInsertedApprovalStatus(currentApproverIndexIn => engStRepeatedAppIndexes(x)
7934 ,approvalStatusIn => ame_util.notifiedByRepeatedStatus);
7935
7936 --+
7937 end if;
7938 end loop;
7939 end if;
7940 end if;
7941 end if;
7942 end if;
7943 --+
7944 --prevApproverOrderNumber := currentTreeNode.min_order;
7945 --prevApproverName := currentTreeNode.tree_level_id;
7946 --prevApproverStatus := currentTreeNode.status;
7947 --+
7948 if currentTreeNode.tree_level = 6 and (prevApproverOrderNumber is null or
7949 prevApproverOrderNumber = currentTreeNode.min_order)
7950 then
7951 if currentTreeNode.status <> ame_util.completedStatus then
7952 prevApproverStatus := currentTreeNode.status;
7953 prevApproverOrderNumber := currentTreeNode.min_order;
7954 prevApproverName := currentTreeNode.tree_level_id;
7955 end if;
7956 end if;
7957 --+
7958 if currentTreeNode.child_index <> ame_util.noChildIndex and evaluateNextNode then
7959 nextTreeNodeIndex := currentTreeNode.child_index;
7960 else
7961 if evaluateNextNode then
7962 nextTreeNodeIndex := currentTreeNode.sibling_index;
7963 if nextTreeNodeIndex <> ame_util.invalidTreeIndex
7964 and (currentTreeNode.min_order = engStApproversTree(nextTreeNodeIndex).min_order
7965 or currentTreeNode.status = ame_util.completedStatus) then
7966 evaluateNextNode := true;
7967 else
7968 evaluateNextNode := false;
7969 end if;
7970 else
7971 nextTreeNodeIndex := ame_util.noSiblingIndex;
7972 end if;
7973 end if;
7974 else
7975 nextTreeNodeIndex := currentTreeNode.sibling_index;
7976 prevApproverOrderNumber := null;
7977 end if;
7978 if nextTreeNodeIndex = ame_util.invalidTreeIndex then
7979 /* There are no more siblings or child nodes for the current node */
7980 /* So try moving to the parent's sibling node */
7981 /* If the parent's sibling is not found then move to its parent */
7982 /* and so on ... */
7983 prevApproverOrderNumber := null;
7984 previousNodeOrderNumber := null;
7985 if currentTreeNode.tree_level = 0 then
7986 tempTreeNodeIndex := ame_util.invalidTreeIndex;
7987 else
7988 tempTreeNodeIndex := currentTreeNode.parent_index;
7989 end if;
7990 if tempTreeNodeIndex <> ame_util.invalidTreeIndex then
7991 processSibling := true;
7992 evaluateNextNode := false;
7993 loop
7994 if engStApproversTree(tempTreeNodeIndex).sibling_index
7995 = ame_util.noSiblingIndex then
7996 tempTreeNodeIndex := engStApproversTree(tempTreeNodeIndex).parent_index;
7997 else
7998 nextTreeNodeIndex := engStApproversTree(tempTreeNodeIndex).sibling_index;
7999 evaluateNextNode := false;
8000 if (engStApproversTree(tempTreeNodeIndex).min_order
8001 = engStApproversTree(nextTreeNodeIndex).min_order
8002 ) or
8003 (engStApproversTree(tempTreeNodeIndex).status
8004 = ame_util.completedStatus )
8005 and
8006 (previousNodeOrderNumber is null or engStApproversTree(tempTreeNodeIndex).min_order = previousNodeOrderNumber
8007 and previousNodeStatus = ame_util.completedStatus
8008 ) then
8009 evaluateNextNode := true;
8010 else
8011 evaluateNextNode := false;
8012 end if;
8013 --+
8014 --previousNodeOrderNumber := engStApproversTree(tempTreeNodeIndex).min_order;
8015 previousTreeLevelId := engStApproversTree(tempTreeNodeIndex).tree_level_id;
8016 --previousNodeStatus := engStApproversTree(tempTreeNodeIndex).status;
8017 if previousNodeOrderNumber is null or previousNodeOrderNumber = engStApproversTree(tempTreeNodeIndex).min_order
8018 then
8019 if engStApproversTree(tempTreeNodeIndex).status <> ame_util.completedStatus then
8020 previousNodeStatus := engStApproversTree(tempTreeNodeIndex).status;
8021 previousNodeOrderNumber := engStApproversTree(tempTreeNodeIndex).min_order;
8022 end if;
8023 end if;
8024 --+
8025 exit;
8026 end if;
8027 if tempTreeNodeIndex = 1 or tempTreeNodeIndex = ame_util.invalidTreeIndex then
8028 nextTreeNodeIndex := ame_util.invalidTreeIndex;
8029 exit;
8030 end if;
8031 end loop;
8032 end if;
8033 end if;
8034 /* When ever we reach this point we come with a valid node which needs */
8035 /* be processed by the next pass of the loop. If no valid node is present */
8036 /* this indicates that the entire tree is traversed and there are no more */
8037 /* approvers to find */
8038 exit when nextTreeNodeIndex = ame_util.invalidTreeIndex;
8039 end loop;
8040 if copyAncillaryData and nextApproversType < 4 then
8041 ame_engine.prepareItemData(approverIndexesIn => tempApproverIndexes
8042 ,itemIndexesOut => itemIndexesOut
8043 ,itemItemClassesOut => itemClassesOut
8044 ,itemIdsOut => itemIdsOut
8045 ,itemSourcesOut => itemSourcesOut);
8046 if nextApproversType = 2 or nextApproversType = 3 then
8047 preparePerApproverProductions
8048 (approverIndexesIn => tempApproverIndexes
8049 ,itemIndexesIn => itemIndexesOut
8050 ,itemSourcesIn => itemSourcesOut
8051 ,prodIndexesOut => productionIndexesOut
8052 ,productionNamesOut => variableNamesOut
8053 ,productionValuesOut => variableValuesOut);
8054 end if;
8055 end if;
8056 if nextApproversType = 3 then
8057 getTransVariableNames(transVariableNamesOut => transVariableNamesOut);
8058 getTransVariableValues(transVariableValuesOut => transVariableValuesOut);
8059 end if;
8060 if flagApproversAsNotifiedIn = ame_util.booleanTrue then
8061 ameApplicationId := ame_engine.getAmeApplicationId;
8062 for i in 1 .. nextApproversOut.count loop
8063 update ame_temp_old_approver_lists
8064 set approval_status = ame_util.notifiedStatus
8065 where item_class = nextApproversOut(i).item_class
8066 and item_id = nextApproversOut(i).item_id
8067 and name = nextApproversOut(i).name
8068 and action_type_id = nextApproversOut(i).action_type_id
8069 and group_or_chain_id = nextApproversOut(i).group_or_chain_id
8070 and occurrence = nextApproversOut(i).occurrence
8071 and transaction_id = transactionIdIn
8072 and application_id = ameApplicationId;
8073 /* Insert into Approval Notification History Table */
8074 insertIntoTransApprovalHistory
8075 (transactionIdIn => transactionIdIn
8076 ,applicationIdIn => ameApplicationId
8077 ,orderNumberIn => nextApproversOut(i).approver_order_number
8078 ,nameIn => nextApproversOut(i).name
8079 ,appCategoryIn => nextApproversOut(i).approver_category
8080 ,itemClassIn => nextApproversOut(i).item_class
8081 ,itemIdIn => nextApproversOut(i).item_id
8082 ,actionTypeIdIn => nextApproversOut(i).action_type_id
8083 ,authorityIn => nextApproversOut(i).authority
8084 ,statusIn => ame_util.notifiedStatus
8085 ,grpOrChainIdIn => nextApproversOut(i).group_or_chain_id
8086 ,occurrenceIn => nextApproversOut(i).occurrence
8087 ,apiInsertionIn => nextApproversOut(i).api_insertion
8088 ,memberOrderNumberIn => nextApproversOut(i).member_order_number
8089 ,notificationIdIn => null
8090 ,userCommentsIn => null
8091 ,dateClearedIn => null
8092 ,historyTypeIn => 'APPROVERPRESENT');
8093 end loop;
8094 end if;
8095 if tempPrepareItemData then
8096 for x in 1 .. nextApproversOut.count loop
8097 if engStApprovers(tempApproverIndexes(x)).item_class is null then
8098 nextApproversOut(x).item_class := null;
8099 nextApproversOut(x).item_id := null;
8100 nextApproversOut(x).source := null;
8101 end if;
8102 end loop;
8103 end if;
8104 for x in 1 .. nextApproversOut.count loop
8105 if nextApproversOut(x).approval_status = ame_util.repeatedStatus then
8106 nextApproversOut(x).approval_status := null;
8107 end if;
8108 end loop;
8109 ame_engine.unlockTransaction(fndApplicationIdIn => applicationIdIn,
8110 transactionIdIn => transactionIdIn,
8111 transactionTypeIdIn => transactionTypeIn);
8112 exception
8113 when others then
8114 ame_engine.unlockTransaction(fndApplicationIdIn => applicationIdIn,
8115 transactionIdIn => transactionIdIn,
8116 transactionTypeIdIn => transactionTypeIn);
8117 ame_util.runtimeException(packageNameIn => 'ame_engine',
8118 routineNameIn => 'getNextApprovers',
8119 exceptionNumberIn => sqlcode,
8120 exceptionStringIn => sqlerrm);
8121 approvalProcessCompleteYNOut:= null;
8122 nextApproversOut.delete;
8123 raise;
8124 end getNextApprovers;
8125 procedure prepareItemData(approverIndexesIn in ame_util.idList default ame_util.emptyIdList
8126 ,itemIndexesOut out nocopy ame_util.idList
8127 ,itemItemClassesOut out nocopy ame_util.stringList
8128 ,itemIdsOut out nocopy ame_util.stringList
8129 ,itemSourcesOut out nocopy ame_util.longStringList) as
8130 tempItemCount integer;
8131 tempItemClass ame_util.stringType;
8132 tempItemId ame_util.stringType;
8133 tempRuleIdList ame_util.idList;
8134 prevIndex integer;
8135 currentIndex integer;
8136 currentApproverIndex integer;
8137 tempIndex integer;
8138 tempSourceDescription ame_util.longStringType;
8139 tempLength integer;
8140 tempFlag boolean;
8141 tempCount integer;
8142 tempFlag2 boolean;
8143 tempProcessApprover boolean;
8144 tempProcessApprover2 boolean;
8145 begin
8146 tempItemCount := 0;
8147 prevIndex := null;
8148 tempCount := approverIndexesIn.count;
8149 tempFlag2 := false;
8150 if tempCount = 0 then
8151 tempFlag2 := true;
8152 tempCount := engStApprovers.count;
8153 end if;
8154 /* here tempFlag2 = false indicates the procedure invoked from getNextApprovers*/
8155 for i in 1 .. tempCount loop
8156 if tempFlag2 then
8157 currentApproverIndex := i;
8158 else
8159 currentApproverIndex := approverIndexesIn(i);
8160 end if;
8161 tempProcessApprover := false;
8162 tempProcessApprover2 := false;
8163 if not tempFlag2 then
8164 tempProcessApprover := true;
8165 else
8166 if ( engStApprovers(currentApproverIndex).approval_status is null
8167 or engStApprovers(currentApproverIndex).approval_status
8168 not in (ame_util.notifiedByRepeatedStatus
8169 ,ame_util.approvedByRepeatedStatus
8170 ,ame_util.rejectedByRepeatedStatus
8171 ,ame_util.suppressedStatus
8172 ,ame_util.repeatedStatus) ) then
8173 tempProcessApprover := true;
8174 end if;
8175 end if;
8176 if tempProcessApprover then
8177 for j in 1 .. engStRepeatedIndexes.count loop
8178 if engStRepeatedIndexes(j) = currentApproverIndex
8179 and engStRepeatedAppIndexes(j) = currentApproverIndex then
8180 tempItemClass := engStApprovers(currentApproverIndex).item_class;
8181 tempItemId := engStApprovers(currentApproverIndex).item_id;
8182 end if;
8183 end loop;
8184 for j in 1 .. engStRepeatedIndexes.count loop
8185 if engStRepeatedIndexes(j) = currentApproverIndex
8186 and engStRepeatedAppIndexes(j) <> currentApproverIndex then
8187 if tempItemClass <> engStApprovers(engStRepeatedAppIndexes(j)).item_class
8188 or tempItemId <> engStApprovers(engStRepeatedAppIndexes(j)).item_id then
8189 tempProcessApprover2 := true;
8190 end if;
8191 end if;
8192 end loop;
8193 end if;
8194 if tempProcessApprover2 then
8195 prevIndex := null;
8196 for j in 1 .. engStRepeatedIndexes.count loop
8197 if engStRepeatedIndexes(j) = currentApproverIndex then
8198 currentIndex := engStRepeatedAppIndexes(j);
8199 if (currentApproverIndex = currentIndex)
8200 or
8201 (engStApprovers(currentIndex).item_id <> tempItemId
8202 or engStApprovers(currentIndex).item_class <> tempItemClass) then
8203 tempItemCount := tempItemCount + 1;
8204 itemIndexesOut(tempItemCount) := i;
8205 tempFlag := true;
8206 itemItemClassesOut(tempItemCount) := engStApprovers(currentIndex).item_class;
8207 itemIdsOut(tempItemCount) := engStApprovers(currentIndex).item_id;
8208 prevIndex := tempItemCount;
8209 end if;
8210 tempSourceDescription := null;
8211 tempRuleIdList.delete;
8212 ame_util.parseSourceValue(sourceValueIn => engStApprovers(currentIndex).source
8213 ,sourceDescriptionOut => tempSourceDescription
8214 ,ruleIdListOut => tempRuleIdList);
8215 for z in 1 .. tempRuleIdList.count loop
8216 if itemSourcesOut.count >= tempItemCount then
8217 tempIndex := instrb(itemSourcesOut(tempItemCount),tempRuleIdList(z));
8218 else
8219 itemSourcesOut(tempItemCount) := null;
8220 tempIndex := -1;
8221 end if;
8222 if tempIndex = -1 then
8223 ame_util.appendRuleIdToSource(ruleIdIn => tempRuleIdList(z)
8224 ,sourceInOut => itemSourcesOut(tempItemCount));
8225 end if;
8226 end loop;
8227 end if;
8228 end loop;
8229 end if;
8230 if tempFlag and (not engIsLocalTransaction)then
8231 tempFlag := false;
8232 engStApprovers(currentApproverIndex).item_class := null;
8233 engStApprovers(currentApproverIndex).item_id := null;
8234 engStApprovers(currentApproverIndex).source := null;
8235 end if;
8236 end loop;
8237 exception
8238 when others then
8239 ame_util.runtimeException(packageNameIn => 'ame_engine',
8240 routineNameIn => 'prepareItemData',
8241 exceptionNumberIn => sqlcode,
8242 exceptionStringIn => sqlerrm);
8243 itemIndexesOut.delete;
8244 itemItemClassesOut.delete;
8245 itemIdsOut.delete;
8246 itemSourcesOut.delete;
8247 raise;
8248 end prepareItemData;
8249 procedure preparePerApproverProductions
8250 (approverIndexesIn in ame_util.idList default ame_util.emptyIdList
8251 ,itemIndexesIn in ame_util.idList default ame_util.emptyIdList
8252 ,itemSourcesIn in ame_util.longStringList default ame_util.emptyLongStringList
8253 ,prodIndexesOut out nocopy ame_util.idList
8254 ,productionNamesOut out nocopy ame_util.stringList
8255 ,productionValuesOut out nocopy ame_util.stringList) as
8256 tempRuleIdList ame_util.idList;
8257 tempSourceDescription ame_util.stringType;
8258 hasRepeatedOccurrences boolean;
8259 currentRepeatedFirstIndex integer;
8260 currentIndex integer;
8261 tempCount integer;
8262 tempPerAppProdIndex integer;
8263 tempProdIndex integer;
8264 tempFlag2 boolean;
8265 tempCount2 integer;
8266 currentApproverIndex integer;
8267 begin
8268 if not engProcessProductionActions then
8269 return;
8270 end if;
8271 tempProdIndex := 0;
8272 tempPerAppProdIndex := 0;
8273 tempCount := 1;
8274 tempCount2 := approverIndexesIn.count;
8275 tempFlag2 := false;
8276 if tempCount2 = 0 then
8277 tempFlag2 := true;
8278 tempCount2 := engStApprovers.count;
8279 end if;
8280 /* here tempFlag2 = false indicates the procedure invoked from getNextApprovers */
8281 for i in 1 .. tempCount2 loop
8282 hasRepeatedOccurrences := false;
8283 currentRepeatedFirstIndex := -1;
8284 tempRuleIdList.delete;
8285 tempSourceDescription := null;
8286 tempCount := 1;
8287 if tempFlag2 then
8288 currentApproverIndex := i;
8289 else
8290 currentApproverIndex := approverIndexesIn(i);
8291 end if;
8292 if tempFlag2 then
8293 if engStApprovers(currentApproverIndex).item_class is null then
8294 tempCount := 0;
8295 for x in 1 .. engStItemIndexes.count loop
8296 if engStItemIndexes(x) = currentApproverIndex then
8297 tempCount := tempCount + 1;
8298 if currentRepeatedFirstIndex = -1 then
8299 currentRepeatedFirstIndex := x;
8300 end if;
8301 end if;
8302 end loop;
8303 hasRepeatedOccurrences := true;
8304 end if;
8305 else
8306 tempCount := 0;
8307 for x in 1 .. itemIndexesIn.count loop
8308 if itemIndexesIn(x) = i then
8309 tempCount := tempCount + 1;
8310 if currentRepeatedFirstIndex = -1 then
8311 currentRepeatedFirstIndex := x;
8312 end if;
8313 end if;
8314 end loop;
8315 if currentRepeatedFirstIndex <> -1 then
8316 hasRepeatedOccurrences := true;
8317 else
8318 hasRepeatedOccurrences := false;
8319 tempCount := 1;
8320 end if;
8321 end if;
8322 currentIndex := 0;
8323 for j in 1 .. tempCount loop
8324 if hasRepeatedOccurrences then
8325 currentIndex := (currentRepeatedFirstIndex+j)-1;
8326 else
8327 currentIndex := currentApproverIndex;
8328 end if;
8329 tempSourceDescription := null;
8330 tempRuleIdList.delete;
8331 if hasRepeatedOccurrences then
8332 if tempFlag2 then
8333 ame_util.parseSourceValue(sourceValueIn => engStItemSources(currentIndex),
8334 sourceDescriptionOut => tempSourceDescription,
8335 ruleIdListOut => tempRuleIdList);
8336 else
8337 ame_util.parseSourceValue(sourceValueIn => itemSourcesIn(currentIndex),
8338 sourceDescriptionOut => tempSourceDescription,
8339 ruleIdListOut => tempRuleIdList);
8340 end if;
8341 else
8342 ame_util.parseSourceValue(sourceValueIn => engStApprovers(currentIndex).source,
8343 sourceDescriptionOut => tempSourceDescription,
8344 ruleIdListOut => tempRuleIdList);
8345 end if;
8346 for k in 1 .. tempRuleIdList.count loop
8347 if(engAppPerAppProdFirstIndexes.exists(tempRuleIdList(k))) then
8348 tempPerAppProdIndex := engAppPerAppProdFirstIndexes(tempRuleIdList(k));
8349 loop
8350 tempProdIndex := tempProdIndex + 1;
8351 prodIndexesOut(tempProdIndex) := i;
8352 productionNamesOut(tempProdIndex) := engAppPerAppProdVariableNames(tempPerAppProdIndex);
8353 productionValuesOut(tempProdIndex) := engAppPerAppProdVariableValues(tempPerAppProdIndex);
8354 tempPerAppProdIndex := tempPerAppProdIndex + 1;
8355 if(not engAppPerAppProdRuleIds.exists(tempPerAppProdIndex) or
8356 engAppPerAppProdRuleIds(tempPerAppProdIndex) <> tempRuleIdList(k)) then
8357 exit;
8358 end if;
8359 end loop;
8360 end if;
8361 end loop;
8362 end loop;
8363 end loop;
8364 exception
8365 when others then
8366 ame_util.runtimeException(packageNameIn => 'ame_engine',
8367 routineNameIn => 'preparePerApproverProductions',
8368 exceptionNumberIn => sqlcode,
8369 exceptionStringIn => sqlerrm);
8370 prodIndexesOut.delete;
8371 productionNamesOut.delete;
8372 productionValuesOut.delete;
8373 raise;
8374 end preparePerApproverProductions;
8375 procedure prepareRuleData as
8376 tempRuleIdList ame_util.idList;
8377 tempEngStRuleIndex integer;
8378 tempSourceDescription ame_util.stringType;
8379 hasRepeatedOccurrences boolean;
8380 currentRepeatedFirstIndex integer;
8381 currentIndex integer;
8382 tempCount integer;
8383 tempEngStProdIndex integer;
8384 begin
8385 if not (engPrepareRuleIds
8386 or engPrepareRuleDescs ) then
8387 return;
8388 end if;
8389 tempEngStRuleIndex := 0;
8390 tempCount := 1;
8391 for i in 1 .. engStApprovers.count loop
8392 hasRepeatedOccurrences := false;
8393 currentRepeatedFirstIndex := -1;
8394 tempRuleIdList.delete;
8395 tempSourceDescription := null;
8396 tempCount := 1;
8397 if engStApprovers(i).item_class is null then
8398 tempCount := 0;
8399 for x in 1 .. engStItemIndexes.count loop
8400 if engStItemIndexes(x) = i then
8401 tempCount := tempCount + 1;
8402 if currentRepeatedFirstIndex = -1 then
8403 currentRepeatedFirstIndex := x;
8404 end if;
8405 end if;
8406 end loop;
8407 hasRepeatedOccurrences := true;
8408 end if;
8409 currentIndex := 0;
8410 for j in 1 .. tempCount loop
8411 if hasRepeatedOccurrences then
8412 currentIndex := (currentRepeatedFirstIndex+j)-1;
8413 else
8414 currentIndex := i;
8415 end if;
8416 tempSourceDescription := null;
8417 tempRuleIdList.delete;
8418 if hasRepeatedOccurrences then
8419 ame_util.parseSourceValue(sourceValueIn => engStItemSources(currentIndex),
8420 sourceDescriptionOut => tempSourceDescription,
8421 ruleIdListOut => tempRuleIdList);
8422 else
8423 ame_util.parseSourceValue(sourceValueIn => engStApprovers(currentIndex).source,
8424 sourceDescriptionOut => tempSourceDescription,
8425 ruleIdListOut => tempRuleIdList);
8426 end if;
8427 if(tempRuleIdList.count = 0) then
8428 tempEngStRuleIndex := tempEngStRuleIndex + 1;
8429 engStRuleIndexes(tempEngStRuleIndex) := i;
8430 engStSourceTypes(tempEngStRuleIndex) := tempSourceDescription;
8431 if(engPrepareRuleIds) then
8432 engStRuleIds(tempEngStRuleIndex) := null;
8433 end if;
8434 if(engPrepareRuleDescs) then
8435 engStRuleDescriptions(tempEngStRuleIndex) := null;
8436 end if;
8437 else
8438 for k in 1 .. tempRuleIdList.count loop
8439 tempEngStRuleIndex := tempEngStRuleIndex + 1;
8440 engStRuleIndexes(tempEngStRuleIndex) := i;
8441 engStSourceTypes(tempEngStRuleIndex) := tempSourceDescription;
8442 if(engPrepareRuleIds) then
8443 engStRuleIds(tempEngStRuleIndex) := tempRuleIdList(k);
8444 end if;
8445 if(engPrepareRuleDescs) then
8446 engStRuleDescriptions(tempEngStRuleIndex) :=
8447 ame_rule_pkg.getDescription(ruleIdIn => tempRuleIdList(k),
8448 processingDateIn => engEffectiveRuleDate);
8449 end if;
8450 end loop;
8451 end if;
8452 end loop;
8453 end loop;
8454 exception
8455 when others then
8456 ame_util.runtimeException(packageNameIn => 'ame_engine',
8457 routineNameIn => 'prepareRuleData',
8458 exceptionNumberIn => sqlcode,
8459 exceptionStringIn => sqlerrm);
8460 engStRuleDescriptions.delete;
8461 engStRuleIds.delete;
8462 engStRuleIndexes.delete;
8463 raise;
8464 end prepareRuleData;
8465 procedure getProductionIndexes(productionIndexesOut out nocopy ame_util.idList) as
8466 begin
8467 for i in 1 .. engStProductionIndexes.count loop
8468 productionIndexesOut(i) := engStProductionIndexes(i);
8469 end loop;
8470 exception
8471 when others then
8472 ame_util.runtimeException(packageNameIn => 'ame_engine',
8473 routineNameIn => 'getProductionIndexes',
8474 exceptionNumberIn => sqlcode,
8475 exceptionStringIn => sqlerrm);
8476 raise;
8477 end getProductionIndexes;
8478 procedure getRepeatedIndexes(repeatedIndexesOut out nocopy ame_util.idList
8479 ,repeatedAppIndexesOut out nocopy ame_util.idList) as
8480 begin
8481 for i in 1 .. engStRepeatedIndexes.count loop
8482 repeatedIndexesOut(i) := engStRepeatedIndexes(i);
8483 end loop;
8484 for i in 1 .. engStRepeatedAppIndexes.count loop
8485 repeatedAppIndexesOut(i) := engStRepeatedAppIndexes(i);
8486 end loop;
8487 exception
8488 when others then
8489 ame_util.runtimeException(packageNameIn => 'ame_engine',
8490 routineNameIn => 'getRepeatedIndexes',
8491 exceptionNumberIn => sqlcode,
8492 exceptionStringIn => sqlerrm);
8493 raise;
8494 end getRepeatedIndexes;
8495 procedure getRuleDescriptions(ruleDescriptionsOut out nocopy ame_util.stringList) as
8496 begin
8497 for i in 1 .. engStRuleDescriptions.count loop
8498 ruleDescriptionsOut(i) := engStRuleDescriptions(i);
8499 end loop;
8500 exception
8501 when others then
8502 ame_util.runtimeException(packageNameIn => 'ame_engine',
8503 routineNameIn => 'getRuleDescriptions',
8504 exceptionNumberIn => sqlcode,
8505 exceptionStringIn => sqlerrm);
8506 raise;
8507 end getRuleDescriptions;
8508 procedure getRuleIds(ruleIdsOut out nocopy ame_util.idList) as
8509 begin
8510 for i in 1 .. engStRuleIds.count loop
8511 ruleIdsOut(i) := engStRuleIds(i);
8512 end loop;
8513 exception
8514 when others then
8515 ame_util.runtimeException(packageNameIn => 'ame_engine',
8516 routineNameIn => 'getRuleIds',
8517 exceptionNumberIn => sqlcode,
8518 exceptionStringIn => sqlerrm);
8519 raise;
8520 end getRuleIds;
8521 procedure getRuleIndexes(ruleIndexesOut out nocopy ame_util.idList) as
8522 begin
8523 for i in 1 .. engStRuleIndexes.count loop
8524 ruleIndexesOut(i) := engStRuleIndexes(i);
8525 end loop;
8526 exception
8527 when others then
8528 ame_util.runtimeException(packageNameIn => 'ame_engine',
8529 routineNameIn => 'getRuleIndexes',
8530 exceptionNumberIn => sqlcode,
8531 exceptionStringIn => sqlerrm);
8532 raise;
8533 end getRuleIndexes;
8534 procedure getRuntimeGroupMembers(groupIdIn in integer,
8535 approverNamesOut out nocopy ame_util.longStringList,
8536 approverOrderNumbersOut out nocopy ame_util.idList,
8537 approverDisplayNamesOut out nocopy ame_util.longStringList,
8538 origSystemIdsOut out nocopy ame_util.idList,
8539 origSystemsOut out nocopy ame_util.stringList) as
8540 firstNewIndex integer;
8541 tempIndex integer;
8542 begin
8543 tempIndex := 0; /* pre-increment */
8544 -- Check if group is defined or has to be re run for every item class/item ID
8545 if(not engGroupUseItemBind.exists(groupIdIn)) then
8546 fetchRuntimeGroup(groupIdIn => groupIdIn);
8547 elsif (engGroupUseItemBind(groupIdIn) = ame_util.booleanTrue) then
8548 fetchRuntimeGroup(groupIdIn => groupIdIn);
8549 end if;
8550 for i in 1 .. engGroupMemberGroupIds.count loop
8551 if(engGroupMemberGroupIds(i) = groupIdIn) then
8552 tempIndex := tempIndex + 1;
8553 approverNamesOut(tempIndex) := engGroupMemberNames(i);
8554 approverOrderNumbersOut(tempIndex) := engGroupMemberOrderNumbers(i);
8555 approverDisplayNamesOut(tempIndex) := engGroupMemberDisplayNames(i);
8556 origSystemsOut(tempIndex) := engGroupMemberOrigSystems(i);
8557 origSystemIdsOut(tempIndex) := engGroupMemberOrigSystemIds(i);
8558 elsif(tempIndex > 0) then /* We found and have passed the group. */
8559 exit;
8560 end if;
8561 end loop;
8562 /*
8563 If the group is the last one in the engGroup package variables, the above loop
8564 will never arrive at its exit statement, so we need to check for a found group
8565 outside the loop.
8566 */
8567 if(tempIndex > 0) then
8568 return;
8569 end if;
8570 exception
8571 when others then
8572 ame_util.runtimeException(packageNameIn => 'ame_engine',
8573 routineNameIn => 'getRuntimeGroupMembers',
8574 exceptionNumberIn => sqlcode,
8575 exceptionStringIn => sqlerrm);
8576 raise;
8577 end getRuntimeGroupMembers;
8578 procedure getSourceTypes(sourceTypesOut out nocopy ame_util.stringList) as
8579 begin
8580 for i in 1 .. engStSourceTypes.count loop
8581 sourceTypesOut(i) := engStSourceTypes(i);
8582 end loop;
8583 exception
8584 when others then
8585 ame_util.runtimeException(packageNameIn => 'ame_engine',
8586 routineNameIn => 'getSourceTypes',
8587 exceptionNumberIn => sqlcode,
8588 exceptionStringIn => sqlerrm);
8589 raise;
8590 end getSourceTypes;
8591 procedure getTestTransApplicableRules(ruleItemClassIdsOut out nocopy ame_util.idList,
8592 itemClassIdsOut out nocopy ame_util.idList,
8593 itemIdsOut out nocopy ame_util.stringList,
8594 ruleIdsOut out nocopy ame_util.idList,
8595 ruleTypesOut out nocopy ame_util.idList,
8596 ruleDescriptionsOut out nocopy ame_util.stringList) as
8597 headerItemClassId integer;
8598 switchRows boolean;
8599 tempIndex integer;
8600 tempItemClassId integer;
8601 tempItemId ame_util.stringType;
8602 tempRuleDescription ame_util.stringType;
8603 tempRuleId integer;
8604 tempRuleItemClassId integer;
8605 tempRuleNotFound boolean;
8606 tempRuleType integer;
8607 begin
8608 headerItemClassId := ame_admin_pkg.getItemClassIdByName(itemClassNameIn => ame_util.headerItemClassName);
8609 /* First populate the output lists, eliminating duplicate rules. */
8610 tempIndex := 0; /* pre-increment */
8611 for i in 1 .. engAppRuleIds.count loop
8612 tempRuleNotFound := true;
8613 for j in 1 .. (i - 1) loop
8614 if(engAppRuleIds(j) = engAppRuleIds(i) and
8615 engAppItemClassIds(i) = engAppItemClassIds(j) and
8616 engAppItemIds(i) = engAppItemIds(j)) then
8617 tempRuleNotFound := false;
8618 exit;
8619 end if;
8620 end loop;
8621 if(tempRuleNotFound) then
8622 tempIndex := tempIndex + 1;
8623 ruleIdsOut(tempIndex) := engAppRuleIds(i);
8624 itemClassIdsOut(tempIndex) := engAppItemClassIds(i);
8625 itemIdsOut(tempIndex) := engAppItemIds(i);
8626 ruleTypesOut(tempIndex) := ame_rule_pkg.getRuleType(ruleIdIn => engAppRuleIds(i),
8627 processingDateIn => engEffectiveRuleDate);
8628 ruleItemClassIdsOut(tempIndex) := ame_rule_pkg.getItemClassId(ruleIdIn => engAppRuleIds(i),
8629 processingDateIn => engEffectiveRuleDate);
8630 ruleDescriptionsOut(tempIndex) := ame_rule_pkg.getDescription(ruleIdIn => engAppRuleIds(i),
8631 processingDateIn => engEffectiveRuleDate);
8632 end if;
8633 end loop;
8634 /*
8635 Now sort the output lists. The header-level rules come first, then all other rules. Among
8636 the header-level rules, sort first by ruleTypesOut, then by itemClassIdsOut, then by itemIdsOut.
8637 (The sort by item class and item ID is only relevant under per-item evaluation, but it's harmless
8638 otherwise, and efficiency is not a concern here.) Among the non-header-level rules, sort first
8639 by ruleItemClassIdsOut, then by itemClassIdsOut, then by itemIdsOut, then by ruleTypesOut.
8640 */
8641 for i in 2 .. ruleItemClassIdsOut.count loop
8642 for j in 1 .. (i - 1) loop
8643 if(ruleItemClassIdsOut(j) = headerItemClassId and
8644 ruleItemClassIdsOut(i) = headerItemClassId) then
8645 if(ruleTypesOut(i) > ruleTypesOut(j)) then
8646 switchRows := false;
8647 elsif(ruleTypesOut(i) < ruleTypesOut(j)) then
8648 switchRows := true;
8649 else /* ruleTypesOut(i) = ruleTypesOut(j) */
8650 if(itemClassIdsOut(i) > itemClassIdsOut(j)) then
8651 switchRows := false;
8652 elsif(itemClassIdsOut(i) < itemClassIdsOut(j)) then
8653 switchRows := true;
8654 else /* itemClassIdsOut(i) = itemClassIdsOut(j) */
8655 if(itemIdsOut(i) > itemIdsOut(j)) then
8656 switchRows := false;
8657 elsif(itemIdsOut(i) < itemIdsOut(j)) then
8658 switchRows := true;
8659 else /* itemIdsOut(i) = itemIdsOut(j) */
8660 switchRows := false;
8661 end if;
8662 end if;
8663 end if;
8664 elsif(ruleItemClassIdsOut(j) = headerItemClassId and
8665 (ruleItemClassIdsOut(i) is null or
8666 ruleItemClassIdsOut(i) <> headerItemClassId)) then
8667 switchRows := false;
8668 elsif((ruleItemClassIdsOut(j) is null or
8669 ruleItemClassIdsOut(j) <> headerItemClassId) and
8670 ruleItemClassIdsOut(i) = headerItemClassId) then
8671 switchRows := true;
8672 else /* ruleItemClassIdsOut(j) <> headerItemClassId and ruleItemClassIdsOut(i) <> headerItemClassId */
8673 if(ruleItemClassIdsOut(i) > ruleItemClassIdsOut(j) or
8674 (ruleItemClassIdsOut(i) is null and ruleItemClassIdsOut(j) is not null)) then
8675 switchRows := false;
8676 elsif(ruleItemClassIdsOut(i) < ruleItemClassIdsOut(j) or
8677 (ruleItemClassIdsOut(i) is not null and ruleItemClassIdsOut(j) is null)) then
8678 switchRows := true;
8679 else /* ruleItemClassIdsOut(i) = ruleItemClassIdsOut(j) or both are null */
8680 if(itemClassIdsOut(i) > itemClassIdsOut(j)) then
8681 switchRows := false;
8682 elsif(itemClassIdsOut(i) < itemClassIdsOut(j)) then
8683 switchRows := true;
8684 else /* itemClassIdsOut(i) = itemClassIdsOut(j) */
8685 if(itemIdsOut(i) > itemIdsOut(j)) then
8686 switchRows := false;
8687 elsif(itemIdsOut(i) < itemIdsOut(j)) then
8688 switchRows := true;
8689 else /* itemIdsOut(i) = itemIdsOut(j) */
8690 switchRows := false;
8691 end if;
8692 end if;
8693 end if;
8694 end if;
8695 if(switchRows) then
8696 /* Assign i values to temp buffers. */
8697 tempRuleItemClassId := ruleItemClassIdsOut(i);
8698 tempItemClassId := itemClassIdsOut(i);
8699 tempItemId := itemIdsOut(i);
8700 tempRuleId := ruleIdsOut(i);
8701 tempRuleType := ruleTypesOut(i);
8702 tempRuleDescription := ruleDescriptionsOut(i);
8703 /* Assign j values to i values. */
8704 ruleItemClassIdsOut(i) := ruleItemClassIdsOut(j);
8705 itemClassIdsOut(i) := itemClassIdsOut(j);
8706 itemIdsOut(i) := itemIdsOut(j);
8707 ruleIdsOut(i) := ruleIdsOut(j);
8708 ruleTypesOut(i) := ruleTypesOut(j);
8709 ruleDescriptionsOut(i) := ruleDescriptionsOut(j);
8710 /* Assign temp buffers to j values. */
8711 ruleItemClassIdsOut(j) := tempRuleItemClassId;
8712 itemClassIdsOut(j) := tempItemClassId;
8713 itemIdsOut(j) := tempItemId;
8714 ruleIdsOut(j) := tempRuleId;
8715 ruleTypesOut(j) := tempRuleType;
8716 ruleDescriptionsOut(j) := tempRuleDescription;
8717 end if;
8718 end loop;
8719 end loop;
8720 exception
8721 when others then
8722 ame_util.runtimeException(packageNameIn => 'ame_engine',
8723 routineNameIn => 'getTestTransApplicableRules',
8724 exceptionNumberIn => sqlcode,
8725 exceptionStringIn => sqlerrm);
8726 raise;
8727 end getTestTransApplicableRules;
8728 procedure getTestTransApprovers(isTestTransactionIn in boolean,
8729 transactionIdIn in varchar2,
8730 ameApplicationIdIn in integer,
8731 approverListStageIn in integer,
8732 approversOut out nocopy ame_util.approversTable2,
8733 productionIndexesOut out nocopy ame_util.idList,
8734 variableNamesOut out nocopy ame_util.stringList,
8735 variableValuesOut out nocopy ame_util.stringList) as
8736 tempCount integer;
8737 begin
8738 if(not isTestTransactionIn) then
8739 /*
8740 Make sure a real transaction gets logged and its state initialized. (This is usually
8741 only necessary for "real" transactions created for debugging purposes.)
8742 */
8743 select count(*)
8744 into tempCount
8745 from ame_temp_transactions
8746 where
8747 application_id = ameApplicationIdIn and
8748 transaction_id = transactionIdIn and
8749 rownum < 2; /* Avoids second fetch otherwise required by ANSI standard to check for too many rows. */
8750 if(tempCount = 0) then
8751 insert into ame_temp_transactions(
8752 application_id,
8753 transaction_id,
8754 temp_transactions_id,
8755 row_timestamp) values(
8756 ameApplicationIdIn,
8757 transactionIdIn,
8758 -1,
8759 sysdate); /* Don't use engEffectiveRuleDate here. */
8760 updateTransactionState(isTestTransactionIn => false,
8761 isLocalTransactionIn => true,
8762 fetchConfigVarsIn => true,
8763 fetchOldApproversIn => true,
8764 fetchInsertionsIn => true,
8765 fetchDeletionsIn => true,
8766 fetchAttributeValuesIn => true,
8767 fetchInactiveAttValuesIn => false,
8768 processProductionActionsIn => false,
8769 processProductionRulesIn => false,
8770 updateCurrentApproverListIn => true,
8771 updateOldApproverListIn => true,
8772 processPrioritiesIn => true,
8773 prepareItemDataIn => true,
8774 prepareRuleIdsIn => true,
8775 prepareRuleDescsIn => false,
8776 prepareApproverTreeIn => true,
8777 transactionIdIn => transactionIdIn,
8778 ameApplicationIdIn => ameApplicationIdIn);
8779 end if;
8780 end if;
8781 setContext(isTestTransactionIn => isTestTransactionIn,
8782 isLocalTransactionIn => true,
8783 fetchConfigVarsIn => true,
8784 fetchOldApproversIn => true,
8785 fetchInsertionsIn => approverListStageIn > 1,
8786 fetchDeletionsIn => approverListStageIn > 2,
8787 fetchAttributeValuesIn => true,
8788 fetchInactiveAttValuesIn => false,
8789 processProductionActionsIn => true,
8790 processProductionRulesIn => true,
8791 updateCurrentApproverListIn => true,
8792 updateOldApproverListIn => true,
8793 processPrioritiesIn => true,
8794 prepareItemDataIn => true,
8795 prepareRuleIdsIn => true,
8796 prepareRuleDescsIn => false,
8797 prepareApproverTreeIn => true,
8798 transactionIdIn => transactionIdIn,
8799 ameApplicationIdIn => ameApplicationIdIn);
8800 evaluateRules;
8801 fetchApplicableActions;
8802 processExceptions;
8803 processRules;
8804 if(approverListStageIn > 1 and not isTestTransactionIn) then
8805 processAdHocInsertions;
8806 processUnresponsiveApprovers;
8807 end if;
8808 if(approverListStageIn > 2 and not isTestTransactionIn) then
8809 if engRepeatSubstitutions then
8810 repeatSubstitutions;
8811 end if;
8812 end if;
8813 if(approverListStageIn > 3 and not isTestTransactionIn) then
8814 processSuppressions;
8815 end if;
8816 if(approverListStageIn > 4) then
8817 processRepeatedApprovers;
8818 end if;
8819 if(approverListStageIn > 5) then
8820 calculateApproverOrderNumbers;
8821 end if;
8822 populateEngStVariables;
8823 getApprovers(approversOut => approversOut);
8824 getProductionIndexes(productionIndexesOut => productionIndexesOut);
8825 getVariableNames(variableNamesOut=> variableNamesOut);
8826 getVariableValues(variableValuesOut => variableValuesOut);
8827 exception
8828 when others then
8829 rollback;
8830 ame_util.runtimeException(packageNameIn => 'ame_engine',
8831 routineNameIn => 'getTestTransApprovers',
8832 exceptionNumberIn => sqlcode,
8833 exceptionStringIn => sqlerrm);
8834 raise;
8835 end getTestTransApprovers;
8836 procedure getTransVariableNames(transVariableNamesOut out nocopy ame_util.stringList) as
8837 tempIndex integer;
8838 begin
8839 tempIndex := 1;
8840 for i in 1 .. engStProductionsTable.count loop
8841 if engStProductionsTable(i).item_class = ame_util.headerItemClassName and
8842 engStProductionsTable(i).item_id = engTransactionId then
8843 transVariableNamesOut(tempIndex) := engStProductionsTable(i).variable_name;
8844 tempIndex := tempIndex + 1;
8845 end if;
8846 end loop;
8847 exception
8848 when others then
8849 ame_util.runtimeException(packageNameIn => 'ame_engine',
8850 routineNameIn => 'getTransVariableNames',
8851 exceptionNumberIn => sqlcode,
8852 exceptionStringIn => sqlerrm);
8853 raise;
8854 end getTransVariableNames;
8855 procedure getTransVariableValues(transVariableValuesOut out nocopy ame_util.stringList) as
8856 tempIndex integer;
8857 begin
8858 tempIndex := 1;
8859 for i in 1 .. engStProductionsTable.count loop
8860 if engStProductionsTable(i).item_class = ame_util.headerItemClassName and
8861 engStProductionsTable(i).item_id = engTransactionId then
8862 transVariableValuesOut(tempIndex) := engStProductionsTable(i).variable_value;
8863 tempIndex := tempIndex + 1;
8864 end if;
8865 end loop;
8866 exception
8867 when others then
8868 ame_util.runtimeException(packageNameIn => 'ame_engine',
8869 routineNameIn => 'getTransVariableValues',
8870 exceptionNumberIn => sqlcode,
8871 exceptionStringIn => sqlerrm);
8872 raise;
8873 end getTransVariableValues;
8874 procedure getVariableNames(variableNamesOut out nocopy ame_util.stringList) as
8875 begin
8876 for i in 1 .. engStVariableNames.count loop
8877 variableNamesOut(i) := engStVariableNames(i);
8878 end loop;
8879 exception
8880 when others then
8881 ame_util.runtimeException(packageNameIn => 'ame_engine',
8882 routineNameIn => 'getVariableNames',
8883 exceptionNumberIn => sqlcode,
8884 exceptionStringIn => sqlerrm);
8885 raise;
8886 end getVariableNames;
8887 procedure getVariableValues(variableValuesOut out nocopy ame_util.stringList) as
8888 begin
8889 for i in 1 .. engStVariableValues.count loop
8890 variableValuesOut(i) := engStVariableValues(i);
8891 end loop;
8892 exception
8893 when others then
8894 ame_util.runtimeException(packageNameIn => 'ame_engine',
8895 routineNameIn => 'getVariableValues',
8896 exceptionNumberIn => sqlcode,
8897 exceptionStringIn => sqlerrm);
8898 raise;
8899 end getVariableValues;
8900 /* initializePlsqlContext is for amem0013.sql backwards compatibility only. Do not use it elsewhere. */
8901 procedure initializePlsqlContext(ameApplicationIdIn in integer default null,
8902 fndApplicationIdIn in integer default null,
8903 transactionIdIn in varchar2 default null,
8904 transactionTypeIdIn in varchar2 default null,
8905 fetchConfigVarsIn in boolean default true,
8906 fetchOldApproversIn in boolean default true,
8907 fetchInsertionsIn in boolean default true,
8908 fetchDeletionsIn in boolean default true,
8909 fetchAttributeValuesIn in boolean default true,
8910 fetchInactiveAttValuesIn in boolean default false) as
8911 begin
8912 setContext(isTestTransactionIn => false,
8913 isLocalTransactionIn => true,
8914 fetchConfigVarsIn => true,
8915 fetchOldApproversIn => true,
8916 fetchInsertionsIn => true,
8917 fetchDeletionsIn => true,
8918 fetchAttributeValuesIn => true,
8919 fetchInactiveAttValuesIn => false,
8920 processProductionActionsIn => false,
8921 processProductionRulesIn => false,
8922 updateCurrentApproverListIn => true,
8923 updateOldApproverListIn => true,
8924 processPrioritiesIn => true,
8925 prepareItemDataIn => false,
8926 prepareRuleIdsIn => false,
8927 prepareRuleDescsIn => false,
8928 prepareApproverTreeIn => false,
8929 transactionIdIn => transactionIdIn,
8930 ameApplicationIdIn => ameApplicationIdIn,
8931 fndApplicationIdIn => null,
8932 transactionTypeIdIn => transactionTypeIdIn);
8933 exception
8934 when others then
8935 ame_util.runtimeException(packageNameIn => 'ame_engine',
8936 routineNameIn => 'initializePlsqlContext',
8937 exceptionNumberIn => sqlcode,
8938 exceptionStringIn => sqlerrm);
8939 raise;
8940 end initializePlsqlContext;
8941 procedure updateDeviationList( sourceIndexIn in number
8942 ,targetIndexIn in number) as
8943 begin
8944 if engDeviationResultList.exists(sourceIndexIn) then
8945 engDeviationResultList(targetIndexIn) := engDeviationResultList(sourceIndexIn);
8946 engDeviationResultList.delete(sourceIndexIn);
8947 else
8948 return;
8949 end if;
8950 exception
8951 when others then
8952 ame_util.runtimeException(packageNameIn => 'ame_engine',
8953 routineNameIn => 'updateDeviationList',
8954 exceptionNumberIn => sqlcode,
8955 exceptionStringIn => sqlerrm);
8956 end updateDeviationList;
8957 procedure insertApprover(indexIn in integer,
8958 approverIn in ame_util.approverRecord2,
8959 adjustMemberOrderNumbersIn in boolean default false,
8960 approverLocationIn in boolean default ame_util.lastAmongEquals,
8961 inserteeIndexIn in number default null,
8962 currentInsIndex in integer default null) as
8963 engStApproversCount integer;
8964 errorCode integer;
8965 errorMessage ame_util.longestStringType;
8966 indexException exception;
8967 lastIndex integer;
8968 nextIndex integer;
8969 nextIndexInChain boolean;
8970 previousIndex integer;
8971 previousIndexInChain boolean;
8972 tempVotingRegime varchar2(1);
8973 approverTreeIndex integer;
8974 l_insIndex number;
8975 l_action_type_id number;
8976 l_votingRegime varchar2(100);
8977 l_action_type_name varchar2(100);
8978 begin
8979 checkApprover(approverIn => approverIn);
8980 engStApproversCount := engStApprovers.count;
8981 if(indexIn < 1 or
8982 indexIn > engStApproversCount + 1) then
8983 raise indexException;
8984 end if;
8985 nextIndex := indexIn + 1;
8986 previousIndex := indexIn - 1;
8987 if(engStApproversCount < nextIndex) then
8988 lastIndex := engStApproversCount;
8989 else
8990 lastIndex := nextIndex;
8991 end if;
8992 /* Move any existing approvers at and above the target index. */
8993 /*
8994 It's necessary to initialize a new record at the end of engStApprovers,
8995 for ame_util.copyApproverRecord2 to work in the loop below.
8996 */
8997 engStApprovers(engStApproversCount + 1) := ame_util.emptyApproverRecord2;
8998 for i in reverse indexIn .. engStApproversCount loop
8999 ame_util.copyApproverRecord2(approverRecord2In => engStApprovers(i),
9000 approverRecord2Out => engStApprovers(i + 1));
9001
9002 l_insIndex := engInsApproverIndex.first;
9003 if l_insIndex is not null then
9004 loop
9005 if engInsApproverIndex(l_insIndex) = i then
9006 engInsApproverIndex(l_insIndex) := null;
9007 engInsApproverIndex(l_insIndex) := i+1;
9008 end if;
9009 exit when l_insIndex = engInsApproverIndex.last;
9010 l_insIndex := engInsApproverIndex.next(l_insIndex);
9011 end loop;
9012 end if;
9013 end loop;
9014 /* Copy the input approver to the target index. */
9015 ame_util.copyApproverRecord2(approverRecord2In => approverIn,
9016 approverRecord2Out => engStApprovers(indexIn));
9017 /*
9018 If the status is not available in ame_temp_insertions get it from
9019 ame_temp_old_approver_lists
9020 */
9021 if engStApprovers(indexIn).approval_status is null then
9022 engStApprovers(indexIn).approval_status := getHandlerApprovalStatus(approverIn => engStApprovers(indexIn)
9023 ,isInsertionapprover => true);
9024 end if;
9025 engStApproversCount := engStApproversCount + 1;
9026 /* Optionally adjust member_order_number values in the target group or chain. */
9027 if(adjustMemberOrderNumbersIn) then
9028 if(indexIn = 1 or
9029 engStApprovers(previousIndex).group_or_chain_id <> approverIn.group_or_chain_id or
9030 engStApprovers(previousIndex).action_type_id <> approverIn.action_type_id or
9031 engStApprovers(previousIndex).item_id <> approverIn.item_id or
9032 engStApprovers(previousIndex).item_class <> approverIn.item_class) then
9033 previousIndexInChain := false;
9034 else
9035 previousIndexInChain := true;
9036 end if;
9037 if(indexIn = engStApprovers.count or
9038 engStApprovers(nextIndex).group_or_chain_id <> approverIn.group_or_chain_id or
9039 engStApprovers(nextIndex).action_type_id <> approverIn.action_type_id or
9040 engStApprovers(nextIndex).item_id <> approverIn.item_id or
9041 engStApprovers(nextIndex).item_class <> approverIn.item_class) then
9042 nextIndexInChain := false;
9043 else
9044 nextIndexInChain := true;
9045 end if;
9046 if(previousIndexInChain) then
9047 if(nextIndexInChain) then
9048 if(engStApprovers(previousIndex).member_order_number =
9049 engStApprovers(nextIndex).member_order_number) then
9050 engStApprovers(indexIn).member_order_number := engStApprovers(previousIndex).member_order_number;
9051 else
9052 engStApprovers(indexIn).member_order_number := engStApprovers(previousIndex).member_order_number + 1;
9053 for i in nextIndex .. engStApproversCount loop
9054 if(engStApprovers(i).item_class <> engStApprovers(indexIn).item_class or
9055 engStApprovers(i).item_id <> engStApprovers(indexIn).item_id or
9056 engStApprovers(i).action_type_id <> engStApprovers(indexIn).action_type_id or
9057 engStApprovers(i).group_or_chain_id <> engStApprovers(indexIn).group_or_chain_id) then
9058 exit;
9059 end if;
9060 engStApprovers(i).member_order_number := engStApprovers(i).member_order_number + 1;
9061 end loop;
9062 end if;
9063 else
9064 if(engStApprovers(previousIndex).approval_status in
9065 (ame_util.approveAndForwardStatus, ame_util.forwardStatus)) then
9066 if(engActionTypeNames(engStApprovers(previousIndex).action_type_id) in
9067 (ame_util.groupChainApprovalTypeName
9068 ,ame_util.preApprovalTypeName
9069 ,ame_util.postApprovalTypeName )) then
9070 select voting_regime
9071 into tempVotingRegime
9072 from ame_approval_group_config
9073 where approval_group_id = engStApprovers(previousIndex).group_or_chain_id
9074 and application_id = engAmeApplicationId
9075 and sysdate between start_date and nvl(end_Date - (1/86400), sysdate);
9076 if(tempVotingRegime not in (ame_util.serializedVoting
9077 ,ame_util.orderNumberVoting)) then
9078 engStApprovers(indexIn).member_order_number := 1;
9079 else
9080 engStApprovers(indexIn).member_order_number := engStApprovers(previousIndex).member_order_number + 1;
9081 end if;
9082 else
9083 if(engActionTypeVotingRegimes(engStApprovers(previousIndex).action_type_id) <>
9084 ame_util.serializedVoting) then
9085 engStApprovers(indexIn).member_order_number := 1;
9086 else
9087 engStApprovers(indexIn).member_order_number := engStApprovers(previousIndex).member_order_number + 1;
9088 end if;
9089 end if;
9090 else
9091 engStApprovers(indexIn).member_order_number := engStApprovers(previousIndex).member_order_number + 1;
9092 end if;
9093 end if;
9094 else
9095 if(nextIndexInChain) then
9096 engStApprovers(indexIn).member_order_number := engStApprovers(nextIndex).member_order_number - 1;
9097 else
9098 engStApprovers(indexIn).member_order_number := 1;
9099 end if;
9100 end if;
9101 end if;
9102 l_action_type_id := engStApprovers(indexIn).action_type_id;
9103 l_action_type_name := getActionTypeName(l_action_type_id);
9104 if l_action_type_name in (ame_util.postApprovalTypeName,ame_util.preApprovalTypeName ) then
9105 l_votingRegime := ame_approval_group_pkg.getVotingRegime(
9106 approvalGroupIdIn => engStApprovers(indexIn).group_or_chain_id ,
9107 applicationIdIn => engAmeApplicationId);
9108 else
9109 l_votingRegime := ame_engine.getActionTypeVotingRegime(actionTypeIdIn => approverIn.action_type_id);
9110 end if;
9111 if engStApprovers(indexIn).approval_status in (ame_util.approvedStatus
9112 ,ame_util.approvedByRepeatedStatus
9113 ,ame_util.rejectStatus
9114 ,ame_util.rejectedByRepeatedStatus ) and l_votingRegime = ame_util.firstApproverVoting then
9115 for i in 1..engStApprovers.count loop
9116 if engStApprovers(indexIn).name <> engStApprovers(i).name and
9117 engStApprovers(indexIn).action_type_id = engStApprovers(i).action_type_id and
9118 engStApprovers(indexIn).group_or_chain_id = engStApprovers(i).group_or_chain_id and
9119 engStApprovers(indexIn).item_class = engStApprovers(i).item_class and
9120 engStApprovers(indexIn).item_id = engStApprovers(i).item_id and
9121 engStApprovers(indexIn).member_order_number = engStApprovers(i).member_order_number and
9122 engStApprovers(i).approval_status is null then
9123 engStApprovers(i).approval_status := ame_util.beatByFirstResponderStatus;
9124 end if;
9125 end loop;
9126 end if;
9127 if engStApprovers(indexIn).approval_status is null and l_votingRegime = ame_util.firstApproverVoting then
9128 if(indexIn <> 1 and indexIn <> engStApprovers.count) then
9129 if(engStApprovers(previousIndex).group_or_chain_id = engStApprovers(indexIn).group_or_chain_id and
9130 engStApprovers(previousIndex).action_type_id = engStApprovers(indexIn).action_type_id and
9131 engStApprovers(previousIndex).item_id = engStApprovers(indexIn).item_id and
9132 engStApprovers(previousIndex).item_class = engStApprovers(indexIn).item_class and
9133 engStApprovers(previousIndex).member_order_number = engStApprovers(indexIn).member_order_number) and
9134 (engStApprovers(nextIndex).group_or_chain_id = engStApprovers(indexIn).group_or_chain_id and
9135 engStApprovers(nextIndex).action_type_id = engStApprovers(indexIn).action_type_id and
9136 engStApprovers(nextIndex).item_id = engStApprovers(indexIn).item_id and
9137 engStApprovers(nextIndex).item_class = engStApprovers(indexIn).item_class and
9138 engStApprovers(nextIndex).member_order_number = engStApprovers(indexIn).member_order_number) then
9139 for i in 1..engStApprovers.count loop
9140 if engStApprovers(indexIn).name <> engStApprovers(i).name and
9141 engStApprovers(indexIn).action_type_id = engStApprovers(i).action_type_id and
9142 engStApprovers(indexIn).group_or_chain_id = engStApprovers(i).group_or_chain_id and
9143 engStApprovers(indexIn).item_class = engStApprovers(i).item_class and
9144 engStApprovers(indexIn).item_id = engStApprovers(i).item_id and
9145 engStApprovers(i).approval_status in (ame_util.approvedStatus
9146 ,ame_util.approvedByRepeatedStatus
9147 ,ame_util.beatByFirstResponderStatus
9148 ,ame_util.rejectStatus
9149 ,ame_util.rejectedByRepeatedStatus ) then
9150 engStApprovers(indexIn).approval_status := ame_util.beatByFirstResponderStatus;
9151 end if;
9152 end loop;
9153 end if;
9154 end if;
9155 end if;
9156 if engPrepareApproverTree and approverIn.orig_system <> 'AME_INS_ORIG_SYSTEM' then
9157 if engStApproversTree.count = 0 then
9158 /* If there are no approvers in tree just add the approver */
9159 if inserteeIndexIn is not null then
9160 engTempReason := engInsertionReasonList(inserteeIndexIn);
9161 engTempDate := engInsertionDateList(inserteeIndexIn);
9162 end if;
9163 addApproverToTree
9164 (approverRecordIn => engStApprovers(indexIn)
9165 ,approverIndexIn => indexIn
9166 ,approverLocationIn => ame_util.lastAmongEquals);
9167 if currentInsIndex is not null then
9168 engInsApproverIndex(currentInsIndex) := indexIn;
9169 end if;
9170 else
9171 /* If there exists approvers in the tree then if adjustMemberOrderNumbersIn */
9172 /* is true update the member order number in the tree */
9173 /* Add the approver to tree */
9174 if adjustMemberOrderNumbersIn then
9175 approverTreeIndex := engStApproversTree.first;
9176 loop
9177 if engStApproversTree(approverTreeIndex).approver_index >= indexIn then
9178 engStApproversTree(approverTreeIndex).order_number
9179 := engStApprovers(engStApproversTree(approverTreeIndex).approver_index + 1).member_order_number;
9180 end if;
9181 exit when approverTreeIndex = engStApproversTree.last;
9182 approverTreeIndex := engStApproversTree.next(approverTreeIndex);
9183 end loop;
9184 end if;
9185 approverTreeIndex := engStApproversTree.first;
9186 loop
9187 if engStApproversTree(approverTreeIndex).approver_index >= indexIn then
9188 engStApproversTree(approverTreeIndex).approver_index := engStApproversTree(approverTreeIndex).approver_index + 1;
9189 end if;
9190 exit when approverTreeIndex = engStApproversTree.last;
9191 approverTreeIndex := engStApproversTree.next(approverTreeIndex);
9192 end loop;
9193 if inserteeIndexIn is not null then
9194 engTempReason := engInsertionReasonList(inserteeIndexIn);
9195 engTempDate := engInsertionDateList(inserteeIndexIn);
9196 end if;
9197 addApproverToTree
9198 (approverRecordIn => engStApprovers(indexIn)
9199 ,approverIndexIn => indexIn
9200 ,approverLocationIn => approverLocationIn);
9201 if currentInsIndex is not null then
9202 engInsApproverIndex(currentInsIndex) := indexIn;
9203 end if;
9204 end if;
9205 end if;
9206 exception
9207 when indexException then
9208 errorCode := -20001;
9209 errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
9210 messageNameIn => 'AME_400686_ENG_IDX_OUT_OF_BOU');
9211 ame_util.runtimeException(packageNameIn => 'ame_engine',
9212 routineNameIn => 'insertApprover',
9213 exceptionNumberIn => errorCode,
9214 exceptionStringIn => errorMessage);
9215 raise_application_error(errorCode,
9216 errorMessage);
9217 when others then
9218 ame_util.runtimeException(packageNameIn => 'ame_engine',
9219 routineNameIn => 'insertApprover',
9220 exceptionNumberIn => sqlcode,
9221 exceptionStringIn => sqlerrm);
9222 raise;
9223 end insertApprover;
9224 procedure insertApprovers(firstIndexIn in integer,
9225 approversIn in ame_util.approversTable2) as
9226 approversInCount integer;
9227 engStApproversCount integer;
9228 errorCode integer;
9229 errorMessage ame_util.longestStringType;
9230 indexException exception;
9231 lastIndex integer;
9232 newTreeNode ame_util.approverTreeRecord;
9233 newTreeNodeIndex integer;
9234 siblingTreeNodeIndex integer;
9235 tempIndex integer;
9236 loopIndex integer;
9237 begin
9238 if(firstIndexIn < 1 or
9239 firstIndexIn > engStApprovers.count + 1) then
9240 raise indexException;
9241 end if;
9242 approversInCount := approversIn.count;
9243 engStApproversCount := engStApprovers.count;
9244 /* This code was modified to fix the BUG:(4093937) */
9245 /* Issue 1 in the list of bugs found during the implementation of the */
9246 /* asynchronous parallel approver functionality */
9247 lastIndex := engStApproversCount;
9248 /* Move any existing approvers at and above firstIndexIn. */
9249 for i in reverse firstIndexIn .. lastIndex loop
9250 ame_util.copyApproverRecord2(approverRecord2In => engStApprovers(i),
9251 approverRecord2Out => engStApprovers(i + approversInCount));
9252 end loop;
9253 /* Copy the input approvers to the target indexes. */
9254 tempIndex := firstIndexIn; /* post-increment */
9255 for i in 1 .. approversInCount loop
9256 ame_util.copyApproverRecord2(approverRecord2In => approversIn(i),
9257 approverRecord2Out => engStApprovers(tempIndex));
9258 tempIndex := tempIndex + 1;
9259 end loop;
9260 /* Insert the new approvers to the tree */
9261 if engPrepareApproverTree then
9262 /* Approvers Tree is sparse */
9263 loopIndex := engStApproversTree.last;
9264 loop
9265 if engStApproversTree(loopIndex).approver_index >= firstIndexIn then
9266 engStApproversTree(loopIndex).approver_index
9267 := engStApproversTree(loopIndex).approver_index + approversIn.count;
9268 elsif engStApproversTree(loopIndex).approver_index = firstIndexIn - 1 then
9269 siblingTreeNodeIndex := engStApproversTree(loopIndex).sibling_index;
9270 for j in reverse 1 .. approversIn.count loop
9271 newTreeNode.parent_index := engStApproversTree(loopIndex).parent_index;
9272 newTreeNode.sibling_index := siblingTreeNodeIndex;
9273 newTreeNode.child_index := ame_util.noChildIndex;
9274 newTreeNode.order_number := approversIn(j).member_order_number;
9275 newTreeNode.approver_index := engStApproversTree(loopIndex).approver_index + j ;
9276 newTreeNode.tree_level_id := approversIn(j).name;
9277 newTreeNode.is_suspended := ame_util.booleanFalse;
9278 newTreeNode.tree_level := 6;
9279 newTreeNodeIndex := engStApproversTree.last + 1;
9280 engStApproversTree(newTreeNodeIndex) := newTreeNode;
9281 siblingTreeNodeIndex := newTreeNodeIndex;
9282 end loop;
9283 engStApproversTree(loopIndex).sibling_index := siblingTreeNodeIndex;
9284 end if;
9285 exit when engStApproversTree.first = loopIndex;
9286 loopIndex := engStApproversTree.prior(loopIndex);
9287 end loop;
9288 end if;
9289 exception
9290 when indexException then
9291 errorCode := -20001;
9292 errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
9293 messageNameIn => 'AME_400687_ENG_FIDX_OUT_OF_BOU');
9294 ame_util.runtimeException(packageNameIn => 'ame_engine',
9295 routineNameIn => 'insertApprovers',
9296 exceptionNumberIn => errorCode,
9297 exceptionStringIn => errorMessage);
9298 raise_application_error(errorCode,
9299 errorMessage);
9300 when others then
9301 ame_util.runtimeException(packageNameIn => 'ame_engine',
9302 routineNameIn => 'insertApprovers',
9303 exceptionNumberIn => sqlcode,
9304 exceptionStringIn => sqlerrm);
9305 raise;
9306 end insertApprovers;
9307 procedure insertIntoTransApprovalHistory
9308 (transactionIdIn ame_trans_approval_history.transaction_id%type
9309 ,applicationIdIn ame_trans_approval_history.application_id%type
9310 ,orderNumberIn ame_trans_approval_history.order_number%type
9311 ,nameIn ame_trans_approval_history.name%type
9312 ,appCategoryIn ame_trans_approval_history.approver_category%type
9313 ,itemClassIn ame_trans_approval_history.item_class%type
9314 ,itemIdIn ame_trans_approval_history.item_id%type
9315 ,actionTypeIdIn ame_trans_approval_history.action_type_id%type
9316 ,authorityIn ame_trans_approval_history.authority%type
9317 ,statusIn ame_trans_approval_history.status%type
9318 ,grpOrChainIdIn ame_trans_approval_history.group_or_chain_id%type
9319 ,occurrenceIn ame_trans_approval_history.occurrence%type
9320 ,apiInsertionIn ame_trans_approval_history.api_insertion%type
9321 ,memberorderNumberIn ame_trans_approval_history.member_order_number%type
9322 ,notificationIdIn ame_trans_approval_history.notification_id%type
9323 ,userCommentsIn ame_trans_approval_history.user_comments%type
9324 ,dateClearedIn ame_trans_approval_history.date_cleared%type
9325 ,historyTypeIn varchar2) as
9326 tempTransHistoryId ame_trans_approval_history.trans_history_id%type;
9327 tempItemClass ame_trans_approval_history.item_class%type;
9328 tempItemId ame_trans_approval_history.item_id%type;
9329 tempOrderNumber ame_trans_approval_history.order_number%type;
9330 tempAuthority ame_trans_approval_history.authority%type;
9331 tempActionTypeId ame_trans_approval_history.action_type_id%type;
9332 tempGroupOrChainId ame_trans_approval_history.group_or_chain_id%type;
9333 tempOccurrence ame_trans_approval_history.occurrence%type;
9334 tempApiInsertion ame_trans_approval_history.api_insertion%type;
9335 tempMemberOrderNumber ame_trans_approval_history.member_order_number%type;
9336 tempName ame_trans_approval_history.name%type;
9337 approvers ame_util.approversTable2;
9338 begin
9339 tempName := nameIn;
9340 if historyTypeIn = 'BEATBYFIRSTRESPONDER' then
9341 ame_engine.getApprovers(approversOut => approvers);
9342 for i in 1 .. approvers.count loop
9343 if (approvers(i).name <> nameIn or approvers(i).occurrence <> occurrenceIn)
9344 and approvers(i).item_class = itemClassIn
9345 and approvers(i).item_id = itemIdIn
9346 and approvers(i).action_type_id = actionTypeIdIn
9347 and approvers(i).group_or_chain_id = grpOrChainIdIn
9348 and approvers(i).approver_category = ame_util.approvalApproverCategory
9349 and approvers(i).approval_status = ame_util.notifiedStatus
9350 then
9351 select ame_trans_approval_history_s.nextval
9352 into tempTransHistoryId
9353 from dual;
9354 insert into AME_TRANS_APPROVAL_HISTORY
9355 (TRANS_HISTORY_ID
9356 ,TRANSACTION_ID
9357 ,APPLICATION_ID
9358 ,ROW_TIMESTAMP
9359 ,ORDER_NUMBER
9360 ,NAME
9361 ,APPROVER_CATEGORY
9362 ,ITEM_CLASS
9363 ,ITEM_ID
9364 ,ACTION_TYPE_ID
9365 ,AUTHORITY
9366 ,STATUS
9367 ,GROUP_OR_CHAIN_ID
9368 ,OCCURRENCE
9369 ,API_INSERTION
9370 ,MEMBER_ORDER_NUMBER
9371 ,NOTIFICATION_ID
9372 ,USER_COMMENTS
9373 ,DATE_CLEARED
9374 )select tempTransHistoryId
9375 ,transactionIdIn
9376 ,applicationIdIn
9377 ,sysdate
9378 ,approvers(i).approver_order_number
9379 ,approvers(i).name
9380 ,approvers(i).approver_category
9381 ,approvers(i).item_class
9382 ,approvers(i).item_id
9383 ,approvers(i).action_type_id
9384 ,approvers(i).authority
9385 ,ame_util.beatByFirstResponderStatus
9386 ,approvers(i).group_or_chain_id
9387 ,approvers(i).occurrence
9388 ,approvers(i).api_insertion
9389 ,approvers(i).member_order_number
9390 ,notificationIdIn
9391 ,null
9392 ,null
9393 from dual;
9394 end if;
9395 end loop;
9396 return;
9397 end if;
9398 if historyTypeIn = 'CLEARFRWGRP' then
9399 ame_engine.getApprovers(approversOut => approvers);
9400 for i in 1 .. approvers.count loop
9401 if (approvers(i).name <> nameIn or approvers(i).occurrence <> occurrenceIn)
9402 and approvers(i).item_class = itemClassIn
9403 and approvers(i).item_id = itemIdIn
9404 and approvers(i).action_type_id = actionTypeIdIn
9405 and approvers(i).group_or_chain_id = grpOrChainIdIn
9406 and approvers(i).approver_category = ame_util.approvalApproverCategory
9407 -- and approvers(i).approval_status = ame_util.notifiedStatus
9408 then
9409 select ame_trans_approval_history_s.nextval
9410 into tempTransHistoryId
9411 from dual;
9412 insert into AME_TRANS_APPROVAL_HISTORY
9413 (TRANS_HISTORY_ID
9414 ,TRANSACTION_ID
9415 ,APPLICATION_ID
9416 ,ROW_TIMESTAMP
9417 ,ORDER_NUMBER
9418 ,NAME
9419 ,APPROVER_CATEGORY
9420 ,ITEM_CLASS
9421 ,ITEM_ID
9422 ,ACTION_TYPE_ID
9423 ,AUTHORITY
9424 ,STATUS
9425 ,GROUP_OR_CHAIN_ID
9426 ,OCCURRENCE
9427 ,API_INSERTION
9428 ,MEMBER_ORDER_NUMBER
9429 ,NOTIFICATION_ID
9430 ,USER_COMMENTS
9431 ,DATE_CLEARED
9432 )select tempTransHistoryId
9433 ,transactionIdIn
9434 ,applicationIdIn
9435 ,sysdate
9436 ,approvers(i).approver_order_number
9437 ,approvers(i).name
9438 ,approvers(i).approver_category
9439 ,approvers(i).item_class
9440 ,approvers(i).item_id
9441 ,approvers(i).action_type_id
9442 ,approvers(i).authority
9443 ,ame_util.beatByFirstResponderStatus
9444 ,approvers(i).group_or_chain_id
9445 ,approvers(i).occurrence
9446 ,approvers(i).api_insertion
9447 ,approvers(i).member_order_number
9448 ,notificationIdIn
9449 ,null
9450 ,null
9451 from dual;
9452 end if;
9453 end loop;
9454 return;
9455 end if;
9456 select ame_trans_approval_history_s.nextval
9457 into tempTransHistoryId
9458 from dual;
9459 if historyTypeIn = 'APPROVERPRESENT' then
9460 insert into AME_TRANS_APPROVAL_HISTORY
9461 (TRANS_HISTORY_ID
9462 ,TRANSACTION_ID
9463 ,APPLICATION_ID
9464 ,ROW_TIMESTAMP
9465 ,ORDER_NUMBER
9466 ,NAME
9467 ,APPROVER_CATEGORY
9468 ,ITEM_CLASS
9469 ,ITEM_ID
9470 ,ACTION_TYPE_ID
9471 ,AUTHORITY
9472 ,STATUS
9473 ,GROUP_OR_CHAIN_ID
9474 ,OCCURRENCE
9475 ,API_INSERTION
9476 ,MEMBER_ORDER_NUMBER
9477 ,NOTIFICATION_ID
9478 ,USER_COMMENTS
9479 ,DATE_CLEARED
9480 )values
9481 (tempTransHistoryId
9482 ,transactionIdIn
9483 ,applicationIdIn
9484 ,sysdate
9485 ,orderNumberIn
9486 ,nameIn
9487 ,appCategoryIn
9488 ,itemClassIn
9489 ,itemIdIn
9490 ,actionTypeIdIn
9491 ,authorityIn
9492 ,statusIn
9493 ,grpOrChainIdIn
9494 ,occurrenceIn
9495 ,apiInsertionIn
9496 ,memberorderNumberIn
9497 ,notificationIdIn
9498 ,userCommentsIn
9499 ,dateClearedIn);
9500 else
9501 begin
9502 select atah.item_class item_class
9503 ,atah.item_id item_id
9504 ,atah.order_number order_number
9505 ,atah.authority authority
9506 ,atah.action_type_id action_type_id
9507 ,atah.group_or_chain_id group_or_chain_id
9508 ,atah.occurrence occurrence
9509 ,atah.api_insertion api_insertion
9510 ,atah.member_order_number member_order_number
9511 into tempItemClass
9512 ,tempItemId
9513 ,tempOrderNumber
9514 ,tempAuthority
9515 ,tempActionTypeId
9516 ,tempGroupOrChainId
9517 ,tempOccurrence
9518 ,tempApiInsertion
9519 ,tempMemberOrderNumber
9520 from ame_trans_approval_history atah
9521 ,fnd_lookups lookup
9522 ,fnd_lookups lookup2
9523 ,ame_approval_groups apg
9524 where atah.date_cleared is null
9525 and atah.transaction_id = transactionIdIn
9526 and atah.application_id = applicationIdIn
9527 and atah.name = tempName
9528 and atah.trans_history_id =
9529 (select max(b.trans_history_id)
9530 from ame_trans_approval_history b
9531 where atah.transaction_id = b.transaction_id
9532 and atah.application_id = b.application_id
9533 and atah.name = b.name
9534 and atah.approver_category = b.approver_category
9535 and atah.item_class = b.item_class
9536 and atah.item_id = b.item_id
9537 and atah.action_type_id = b.action_type_id
9538 and atah.authority = b.authority
9539 and atah.group_or_chain_id = b.group_or_chain_id
9540 and atah.occurrence = b.occurrence
9541 and b.date_cleared is null )
9542 and lookup.lookup_type = 'AME_SUBLIST_TYPES'
9543 and lookup.lookup_code = atah.authority
9544 and lookup2.lookup_type = 'AME_APPROVAL_STATUS'
9545 and lookup2.lookup_code = atah.status
9546 and apg.approval_group_id(+) = atah.group_or_chain_id
9547 and sysdate between nvl(apg.start_date,sysdate) and nvl(apg.end_date,sysdate);
9548 exception
9549 when no_data_found then
9550 tempItemClass := '$AME_INVALID_ITEM_CLASS$';
9551 tempItemId := '$AME_INVALID_ITEM$';
9552 tempOrderNumber := 0;
9553 tempAuthority := 'Y';
9554 tempActionTypeId := ame_util.nullHistoryActionTypeId;
9555 tempGroupOrChainId := ame_util.nullHistoryGroupOrChainId;
9556 tempOccurrence := ame_util.nullHistoryOccurrence;
9557 tempApiInsertion := null;
9558 tempMemberOrderNumber := null;
9559 end;
9560 if orderNumberIn is not null then
9561 tempOrderNumber := orderNumberIn;
9562 end if;
9563 if itemClassIn is not null then
9564 tempItemClass := itemClassIn;
9565 end if;
9566 if itemIdIn is not null then
9567 tempItemId := itemIdIn;
9568 end if;
9569 if grpOrChainIdIn is not null then
9570 tempGroupOrChainId := grpOrChainIdIn;
9571 end if;
9572 if authorityIn is not null then
9573 tempAuthority := authorityIn;
9574 end if;
9575 if actionTypeIdIn is not null then
9576 tempActionTypeId := actionTypeIdIn;
9577 end if;
9578 if occurrenceIn is not null then
9579 tempOccurrence := occurrenceIn;
9580 end if;
9581 if apiInsertionIn is not null then
9582 tempApiInsertion := apiInsertionIn;
9583 end if;
9584 if memberorderNumberIn is not null then
9585 tempMemberOrderNumber := memberorderNumberIn;
9586 end if;
9587 insert into AME_TRANS_APPROVAL_HISTORY
9588 (TRANS_HISTORY_ID
9589 ,TRANSACTION_ID
9590 ,APPLICATION_ID
9591 ,ROW_TIMESTAMP
9592 ,ORDER_NUMBER
9593 ,NAME
9594 ,APPROVER_CATEGORY
9595 ,ITEM_CLASS
9596 ,ITEM_ID
9597 ,ACTION_TYPE_ID
9598 ,AUTHORITY
9599 ,STATUS
9600 ,GROUP_OR_CHAIN_ID
9601 ,OCCURRENCE
9602 ,API_INSERTION
9603 ,MEMBER_ORDER_NUMBER
9604 ,NOTIFICATION_ID
9605 ,USER_COMMENTS
9606 ,DATE_CLEARED
9607 ) values
9608 (tempTransHistoryId
9609 ,transactionIdIn
9610 ,applicationIdIn
9611 ,sysdate
9612 ,tempOrderNumber
9613 ,nameIn
9614 ,appCategoryIn
9615 ,tempItemClass
9616 ,tempItemId
9617 ,tempActionTypeId
9618 ,tempAuthority
9619 ,statusIn
9620 ,tempGroupOrChainId
9621 ,tempOccurrence
9622 ,tempApiInsertion
9623 ,tempMemberOrderNumber
9624 ,notificationIdIn
9625 ,userCommentsIn
9626 ,dateClearedIn
9627 );
9628 end if;
9629 exception
9630 when others then
9631 ame_util.runtimeException(packageNameIn => 'ame_engine',
9632 routineNameIn => 'insertIntoTransApprovalHistory',
9633 exceptionNumberIn => sqlcode,
9634 exceptionStringIn => sqlerrm);
9635
9636 end insertIntoTransApprovalHistory;
9637 procedure lockTransaction(fndApplicationIdIn in integer,
9638 transactionIdIn in varchar2,
9639 transactionTypeIdIn in varchar2 default null) as
9640 tempTransIsLocked varchar2(2);
9641 cursor IsEngLocked is
9642 select 'Y'
9643 from ame_temp_trans_locks
9644 where fnd_application_id = fndApplicationIdIn
9645 and transaction_id = transactionIdIn
9646 and transaction_type_id = transactionTypeIdIn;
9647 begin
9648 /*
9649 The ame_temp_trans_locks_pk unique index will prevent the following insert from occurring
9650 if another row has already been inserted into ame_temp_trans_locks with the same
9651 fnd_application_id, transaction_type_id, and transaction_id values (even though the other
9652 insert is not committed).
9653 */
9654 tempTransIsLocked := null;
9655 if(engTransactionIsLocked) then
9656 return;
9657 end if;
9658 open IsEngLocked;
9659 fetch IsEngLocked into tempTransIsLocked;
9660 close IsEngLocked;
9661 if tempTransIsLocked = 'Y' then
9662 return;
9663 end if;
9664 insert into ame_temp_trans_locks(fnd_application_id,
9665 transaction_type_id,
9666 transaction_id,
9667 row_timestamp) values(
9668 fndApplicationIdIn,
9669 transactionTypeIdIn,
9670 transactionIdIn,
9671 sysdate);
9672 engTransactionIsLocked := true;
9673 exception
9674 when others then
9675 ame_util.runtimeException(packageNameIn => 'ame_engine',
9676 routineNameIn => 'lockTransaction',
9677 exceptionNumberIn => sqlcode,
9678 exceptionStringIn => sqlerrm);
9679 raise;
9680 end lockTransaction;
9681 procedure logTransaction as
9682 tempCount integer:= null;
9683 tempTransSeqId number;
9684 begin
9685 /* Log the transaction for eventual purging from the temp tables. */
9686 select count(*)
9687 into tempCount
9688 from ame_temp_transactions
9689 where
9690 application_id = engAmeApplicationId and
9691 transaction_id = engTransactionId and
9692 rownum < 2; /* Avoids second fetch otherwise required by ANSI standard to check for too many rows. */
9693 if(tempCount = 0) then
9694 select ame_temp_transactions_s.nextval into tempTransSeqId from dual;
9695 insert into ame_temp_transactions(
9696 application_id,
9697 transaction_id,
9698 row_timestamp,
9699 temp_transactions_id
9700 ) values(
9701 engAmeApplicationId,
9702 engTransactionId,
9703 sysdate,
9704 tempTransSeqId); /* Don't use engEffectiveRuleDate here. */
9705 end if;
9706 exception
9707 when others then
9708 ame_util.runtimeException(packageNameIn => 'ame_engine',
9709 routineNameIn => 'logTransaction',
9710 exceptionNumberIn => sqlcode,
9711 exceptionStringIn => sqlerrm);
9712 raise;
9713 end logTransaction;
9714 procedure parseFields(stringIn in varchar2,
9715 fieldsOut out nocopy ame_util.longStringList) as
9716 fieldEnd integer;
9717 fieldIndex integer;
9718 fieldStart integer;
9719 stringLength integer;
9720 begin
9721 stringLength := lengthb(stringIn);
9722 fieldStart := 1;
9723 fieldIndex := 1; /* post-increment */
9724 loop
9725 fieldEnd := instrb(stringIn, ame_util.fieldDelimiter, fieldStart, 1);
9726 if(fieldEnd = 0) then
9727 fieldsOut(fieldIndex) := substrb(stringIn, fieldStart);
9728 exit;
9729 end if;
9730 fieldsOut(fieldIndex) := substrb(stringIn, fieldStart, fieldEnd - fieldStart);
9731 fieldIndex := fieldIndex + 1;
9732 fieldStart := fieldEnd + 1;
9733 end loop;
9734 exception
9735 when others then
9736 ame_util.runtimeException(packageNameIn => 'ame_engine',
9737 routineNameIn => 'parseFields',
9738 exceptionNumberIn => sqlcode,
9739 exceptionStringIn => sqlerrm);
9740 raise;
9741 end parseFields;
9742 procedure parseForwardingBehaviors(forwardingBehaviorsIn in varchar2) as
9743 startPosition integer;
9744 valueLength integer;
9745 begin
9746 startPosition := 1;
9747 for i in 1 .. 8 loop
9748 if(i = 8) then
9749 valueLength := lengthb(substrb(forwardingBehaviorsIn, startPosition));
9750 else
9751 valueLength := instrb(forwardingBehaviorsIn, ':', startPosition + 1, 1) - startPosition;
9752 end if;
9753 engForwardingBehaviors(i) := substrb(forwardingBehaviorsIn, startPosition, valueLength);
9754 startPosition := startPosition + valueLength + 1;
9755 end loop;
9756 exception
9757 when others then
9758 ame_util.runtimeException(packageNameIn => 'ame_engine',
9759 routineNameIn => 'parseForwardingBehaviors',
9760 exceptionNumberIn => sqlcode,
9761 exceptionStringIn => sqlerrm);
9762 raise;
9763 end parseForwardingBehaviors;
9764 procedure parsePriorityModes(priorityModesIn in varchar2) as
9765 currentValue ame_util.stringType;
9766 endPosition integer;
9767 startPosition integer;
9768 underscorePosition integer;
9769 begin
9770 /*
9771 The i - 1 indexes on the left side of the assignments account
9772 for the rule-type constants starting at zero.
9773 */
9774 startPosition := 1;
9775 for i in 1 .. 8 loop
9776 if(i < 8) then
9777 endPosition := instrb(priorityModesIn, ':', startPosition, 1) - 1;
9778 else
9779 endPosition := lengthb(priorityModesIn);
9780 end if;
9781 currentValue := substrb(priorityModesIn, startPosition, endPosition - startPosition + 1);
9782 underscorePosition := instrb(currentValue, '_', 1, 1);
9783 if(underscorePosition = 0) then
9784 engPriorityModes(i - 1) := ame_util.disabledRulePriority;
9785 engPriorityThresholds(i - 1) := null;
9786 else
9787 engPriorityThresholds(i - 1) := to_number(substrb(currentValue, underscorePosition + 1));
9788 if(instrb(currentValue, ame_util.absoluteRulePriority, 1, 1) > 0) then
9789 engPriorityModes(i - 1) := ame_util.absoluteRulePriority;
9790 else
9791 engPriorityModes(i - 1) := ame_util.relativeRulePriority;
9792 end if;
9793 end if;
9794 startPosition := endPosition + 2;
9795 end loop;
9796 exception
9797 when others then
9798 ame_util.runtimeException(packageNameIn => 'ame_engine',
9799 routineNameIn => 'parsePriorityModes',
9800 exceptionNumberIn => sqlcode,
9801 exceptionStringIn => sqlerrm);
9802 raise;
9803 end parsePriorityModes;
9804 procedure populateEngStVariables as
9805 headerItemRejected boolean;
9806 itemIds ame_util.stringList;
9807 itemClasses ame_util.stringList;
9808 tempItemClass ame_util.stringType;
9809 tempItemId ame_util.stringType;
9810 tempItemIndex integer;
9811 tempPseudoBoolean ame_util.charType;
9812 stoppingRule ame_util.stringType;
9813 itemRejected boolean;
9814 tempCount integer;
9815 begin
9816 /*
9817 The procedure processRepeatedApprovers populates most of the engSt variables, to synchronize
9818 that work with the repeatedApprovers functionality, for efficiency. This procedure just
9819 populates engStApprovalProcessCompleteYN, engStItemAppProcessCompleteYN, engStProductionIndexes,
9820 engStVariableNames, and engStVariableValues. Note that this procedure should execute after
9821 processRepeatedApprovers, so it can treat repeated approvers as having approved in the
9822 calculation of the approval-process-complete values.
9823 */
9824 /* Initialize various values. */
9825 itemRejected := false;
9826 engStApprovalProcessCompleteYN := ame_util2.completeNoApprovers;
9827 for i in 1 .. engItemIds.count loop
9828 engStItemAppProcessCompleteYN(i) := ame_util2.completeNoApprovers;
9829 end loop;
9830 /* Handle the empty-approver-list case first. */
9831 if(engStApprovers.count = 0) then
9832 return;
9833 end if;
9834 /* get all itemclasses and itemids of current transaction */
9835 getAllItemClasses(itemClassNamesOut => itemClasses);
9836 getAllItemIds(itemIdsOut => itemIds);
9837 /*
9838 The approver list is non-empty. Set the process-complete values per the statuses in
9839 engStApprovers;
9840 */
9841 /* modified the values of approvalProcessCompleteYN as per bug 4411016 */
9842 /* Initialize the temp variables. */
9843 tempItemId := engStApprovers(1).item_id;
9844 tempItemClass := engStApprovers(1).item_class;
9845 for i in 1 .. itemIds.count loop
9846 if(itemIds(i) = tempItemId and itemClasses(i) = tempItemClass) then
9847 tempItemIndex := i;
9848 engStItemAppProcessCompleteYN(tempItemIndex) := ame_util2.completeFullyApproved;
9849 if engStApprovalProcessCompleteYN = ame_util2.completeNoApprovers then
9850 engStApprovalProcessCompleteYN := ame_util2.completeFullyApproved;
9851 end if;
9852 exit;
9853 end if;
9854 end loop;
9855 tempPseudoBoolean := ame_util.booleanTrue;
9856 /* Loop through the approvers. */
9857 for i in 1 .. engStApprovers.count loop
9858 /* Update the temp variables when the item changes. */
9859 if(engStApprovers(i).item_id <> tempItemId or
9860 engStApprovers(i).item_class <> tempItemClass) then
9861 tempItemId := engStApprovers(i).item_id;
9862 tempItemClass := engStApprovers(i).item_class;
9863 tempPseudoBoolean := ame_util.booleanTrue;
9864 for j in (tempItemIndex + 1) .. itemIds.count loop
9865 if(itemIds(j) = tempItemId and itemClasses(j) = tempItemClass) then
9866 tempItemIndex := j;
9867 engStItemAppProcessCompleteYN(tempItemIndex) := ame_util2.completeFullyApproved;
9868 if engStApprovalProcessCompleteYN = ame_util2.completeNoApprovers then
9869 engStApprovalProcessCompleteYN := ame_util2.completeFullyApproved;
9870 end if;
9871 exit;
9872 end if;
9873 end loop;
9874 end if;
9875 /* Update the process-complete engSt variables as appropriate. */
9876 -- check for pending/yet to be notified approvers
9877 if(engStItemAppProcessCompleteYN(tempItemIndex) <> ame_util2.completeFullyRejected and
9878 ((engStApprovers(i).approver_category = ame_util.approvalApproverCategory and
9879 (engStApprovers(i).approval_status is null or
9880 engStApprovers(i).approval_status in (ame_util.nullStatus
9881 ,ame_util.notifiedStatus
9882 ,ame_util.repeatedStatus
9883 ,ame_util.notifiedByRepeatedStatus))) or
9884 (engStApprovers(i).approver_category = ame_util.fyiApproverCategory and
9885 (engStApprovers(i).approval_status is null or
9886 engStApprovers(i).approval_status = ame_util.nullStatus)))) then
9887 if engStItemAppProcessCompleteYN(tempItemIndex) in (ame_util2.completeNoApprovers
9888 ,ame_util2.completeFullyApproved) then
9889 engStItemAppProcessCompleteYN(tempItemIndex) := ame_util2.notCompleted;
9890 if engStApprovalProcessCompleteYN in (ame_util2.completeNoApprovers
9891 ,ame_util2.completeFullyApproved) then
9892 engStApprovalProcessCompleteYN := ame_util2.notCompleted;
9893 end if;
9894 end if;
9895 end if;
9896 -- check for rejections
9897 if(engStApprovers(i).approver_category = ame_util.approvalApproverCategory and
9898 engStApprovers(i).approval_status in (ame_util.rejectStatus,ame_util.rejectedByRepeatedStatus)) then
9899 itemRejected := true;
9900 if tempItemClass = ame_util.headerItemClassName then
9901 headerItemRejected := true;
9902 end if;
9903 engStItemAppProcessCompleteYN(tempItemIndex) := ame_util2.completeFullyRejected;
9904 end if;
9905 end loop;
9906
9907 if itemRejected then
9908 stoppingRule := ame_engine.getHeaderAttValue2
9909 (attributeNameIn => ame_util.rejectionResponseAttribute);
9910 if stoppingRule is null or stoppingRule not in (ame_util.stopAllItems,ame_util.continueOtherSubItems,
9911 ame_util.continueAllOtherItems) then
9912 stoppingRule := ame_util.stopAllItems;
9913 end if;
9914 -- When the stoppingRule is STOP_ALL_ITEMS or a header item got rejected then
9915 -- 1. The transaction as a whole is rejected.
9916 -- 2. Make all pending items approval status rejected.
9917 if stoppingRule = ame_util.stopAllItems or headerItemRejected then
9918 engStApprovalProcessCompleteYN := ame_util2.completeFullyRejected;
9919 --+
9920 for x in 1 .. itemIds.count loop
9921 if engStItemAppProcessCompleteYN(x) = ame_util2.notCompleted then
9922 engStItemAppProcessCompleteYN(x) := ame_util2.completeFullyRejected;
9923 end if;
9924 end loop;
9925 --+
9926 end if;
9927 -- When the stoppingRule is CONTINUE_OTHER_SUBORDINATE_ITEMS or
9928 -- CONTINUE_ALL_OTHER_ITEMS then
9929 -- 1. Reject header item if stoppingRule is CONTINUE_OTHER_SUBORDINATE_ITEMS
9930 -- and header item is pending.
9931 -- 2. Set the transaction level status to partially rejected by default.
9932 -- 3. If any other item is still pending set the approval status of
9933 -- transaction to pending status.
9934 -- 4. If the transaction level status is still partially rejected then
9935 -- check for complete rejection. Complete rejection will happen if all items
9936 -- are rejected or have no approvers.
9937 if stoppingRule = ame_util.continueOtherSubItems or
9938 stoppingRule = ame_util.continueAllOtherItems then
9939 if stoppingRule = ame_util.continueOtherSubItems then
9940 for x in 1 .. itemIds.count loop
9941 if itemClasses(x) = ame_util.headerItemClassName and
9942 engStItemAppProcessCompleteYN(x) = ame_util2.notCompleted then
9943 engStItemAppProcessCompleteYN(x) := ame_util2.completeFullyRejected;
9944 exit;
9945 end if;
9946 end loop;
9947 end if;
9948 engStApprovalProcessCompleteYN := ame_util2.completePartiallyApproved;
9949 for x in 1 .. itemIds.count loop
9950 if engStItemAppProcessCompleteYN(x) = ame_util2.notCompleted then
9951 engStApprovalProcessCompleteYN := ame_util2.notCompleted;
9952 exit;
9953 end if;
9954 end loop;
9955 tempCount := 0;
9956 if engStApprovalProcessCompleteYN = ame_util2.completePartiallyApproved then
9957 for x in 1 .. itemIds.count loop
9958 if engStItemAppProcessCompleteYN(x) <> ame_util2.completeFullyRejected and
9959 engStItemAppProcessCompleteYN(x) <> ame_util2.completeNoApprovers then
9960 exit;
9961 end if;
9962 tempCount := tempCount + 1;
9963 end loop;
9964 if tempCount = itemIds.count then
9965 engStApprovalProcessCompleteYN := ame_util2.completeFullyRejected;
9966 end if;
9967 end if;
9968 end if;
9969 end if;
9970 if(engSATOFlag = 'Y') then
9971 engStApprovalProcessCompleteYN := ame_util2.notCompleted;
9972 end if;
9973 exception
9974 when others then
9975 ame_util.runtimeException(packageNameIn => 'ame_engine',
9976 routineNameIn => 'populateEngStVariables',
9977 exceptionNumberIn => sqlcode,
9978 exceptionStringIn => sqlerrm);
9979 raise;
9980 end populateEngStVariables;
9981 procedure processAdHocInsertions as
9982 displacedInserteeIndexes ame_util.idList;
9983 engStApproversCount integer;
9984 parameterFields ame_util.longStringList;
9985 tempAnchorIndex integer;
9986 tempBoolean boolean;
9987 tempIndex integer;
9988 tempIndex2 integer;
9989 tempItemClass ame_temp_insertions.item_class%type;
9990 tempItemId ame_temp_insertions.item_id%type;
9991 tempOrderType ame_temp_insertions.order_type%type;
9992 l_error_code number;
9993 errorCode integer;
9994 errorMessage ame_util.longestStringType;
9995 begin
9996 /*
9997 This procedure generally must populate the following ame_util.approverRecord2 fields,
9998 for each inserted approver:
9999 orig_system
10000 orig_system_id
10001 display_name
10002 action_type_id
10003 group_or_chain_id
10004 occurrence
10005 source
10006 approval_status
10007 item_class_order_number
10008 item_order_number
10009 sub_list_order_number
10010 action_type_order_number
10011 group_or_chain_order_number
10012 member_order_number
10013 The first three of these fields get populated at the beginning of the outermost loop below.
10014 The other fields get populated just before the actual insertion occurs. This procedure must
10015 therefore decide how to set the order-number fields. The procedure attempts to set the
10016 order numbers consistent with the order relation of the insertion, where the order relation
10017 anchors the insertion to the approver preceeding or following the insertion in engStApprovers.
10018 See the comments near specific insertApprover calls below.
10019 */
10020 engStApproversCount := engStApprovers.count;
10021 for i in 1 .. engInsertedApproverList.count loop
10022 if(engInsertedApproverList(i).authority <> ame_util.authorityApprover or
10023 engInsertedApproverList(i).api_insertion = ame_util.apiInsertion) then
10024 begin
10025 ame_approver_type_pkg.getOrigSystemIdAndDisplayName(nameIn => engInsertedApproverList(i).name,
10026 origSystemOut => engInsertedApproverList(i).orig_system,
10027 origSystemIdOut => engInsertedApproverList(i).orig_system_id,
10028 displayNameOut => engInsertedApproverList(i).display_name);
10029 exception
10030 when others then
10031 l_error_code := sqlcode;
10032 if l_error_code = -20213 then
10033 if engInsertedApproverList(i).approval_status is null then
10034 errorCode := -20219;
10035 errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
10036 messageNameIn => 'AME_400837_INV_APR_FOUND',
10037 tokenNameOneIn => 'PROCESS_NAME',
10038 tokenValueOneIn => 'ame_engine.processAdHocInsertions',
10039 tokenNameTwoIn => 'NAME',
10040 tokenValueTwoIn => engInsertedApproverList(i).name);
10041 raise_application_error(errorCode,errorMessage);
10042 raise;
10043 end if;
10044 engInsertedApproverList(i).orig_system := 'AME_INS_ORIG_SYSTEM';
10045 end if;
10046 end;
10047 parameterFields.delete;
10048 parseFields(stringIn => engInsertionParameterList(i),
10049 fieldsOut => parameterFields);
10050 /* absoluteOrder */
10051 if(engInsertionOrderTypeList(i) = ame_util.absoluteOrder) then
10052 tempIndex := engInsertionParameterList(i);
10053 if(tempIndex > engStApprovers.count + 1) then
10054 tempIndex := engStApprovers.count + 1;
10055 end if;
10056 engInsertedApproverList(i).source := ame_util.otherInsertion;
10057 if(engStApprovers.exists(tempIndex - 1) and
10058 engStApprovers(tempIndex - 1).authority = engInsertedApproverList(i).authority and
10059 engStApprovers(tempIndex - 1).item_class = engInsertedApproverList(i).item_class and
10060 engStApprovers(tempIndex - 1).item_id = engInsertedApproverList(i).item_id
10061 ) then
10062 /* Group the insertion with the preceeding approver in engStApprovers. */
10063 engInsertedApproverList(i).action_type_id := engStApprovers(tempIndex - 1).action_type_id;
10064 engInsertedApproverList(i).group_or_chain_id := engStApprovers(tempIndex - 1).group_or_chain_id;
10065 engInsertedApproverList(i).occurrence :=
10066 getHandlerOccurrence(nameIn => engInsertedApproverList(i).name,
10067 itemClassIn => engInsertedApproverList(i).item_class,
10068 itemIdIn => engInsertedApproverList(i).item_id,
10069 actionTypeIdIn => engInsertedApproverList(i).action_type_id,
10070 groupOrChainIdIn => engInsertedApproverList(i).group_or_chain_id);
10071 engInsertedApproverList(i).item_class_order_number :=
10072 engStApprovers(tempIndex - 1).item_class_order_number;
10073 engInsertedApproverList(i).item_order_number := engStApprovers(tempIndex - 1).item_order_number;
10074 engInsertedApproverList(i).sub_list_order_number := engStApprovers(tempIndex - 1).sub_list_order_number;
10075 engInsertedApproverList(i).action_type_order_number :=
10076 engStApprovers(tempIndex - 1).action_type_order_number;
10077 engInsertedApproverList(i).group_or_chain_order_number :=
10078 engStApprovers(tempIndex - 1).group_or_chain_order_number;
10079 elsif(engStApprovers.exists(tempIndex)) then
10080 /* Group the insertion with the following approver in engStApprovers. */
10081 engInsertedApproverList(i).authority := engStApprovers(tempIndex).authority;
10082 engInsertedApproverList(i).action_type_id := engStApprovers(tempIndex).action_type_id;
10083 engInsertedApproverList(i).group_or_chain_id := engStApprovers(tempIndex).group_or_chain_id;
10084 engInsertedApproverList(i).occurrence :=
10085 getHandlerOccurrence(nameIn => engInsertedApproverList(i).name,
10086 itemClassIn => engInsertedApproverList(i).item_class,
10087 itemIdIn => engInsertedApproverList(i).item_id,
10088 actionTypeIdIn => engInsertedApproverList(i).action_type_id,
10089 groupOrChainIdIn => engInsertedApproverList(i).group_or_chain_id);
10090 engInsertedApproverList(i).item_class_order_number := engStApprovers(tempIndex).item_class_order_number;
10091 engInsertedApproverList(i).item_order_number := engStApprovers(tempIndex).item_order_number;
10092 engInsertedApproverList(i).sub_list_order_number := engStApprovers(tempIndex).sub_list_order_number;
10093 engInsertedApproverList(i).action_type_order_number := engStApprovers(tempIndex).action_type_order_number;
10094 engInsertedApproverList(i).group_or_chain_order_number :=
10095 engStApprovers(tempIndex).group_or_chain_order_number;
10096 else
10097 /* engStApprovers must be empty. */
10098 engInsertedApproverList(i).action_type_id := ame_util.nullInsertionActionTypeId;
10099 engInsertedApproverList(i).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
10100 engInsertedApproverList(i).occurrence := 1;
10101 engInsertedApproverList(i).item_class_order_number :=
10102 getItemClassOrderNumber(itemClassIdIn =>
10103 getItemClassId(itemClassNameIn => engInsertedApproverList(i).item_class));
10104 engInsertedApproverList(i).item_order_number :=
10105 getItemOrderNumber(itemClassNameIn => engInsertedApproverList(i).item_class,
10106 itemIdIn => engInsertedApproverList(i).item_id);
10107 engInsertedApproverList(i).sub_list_order_number :=
10108 getSublistOrderNum(itemClassNameIn => ame_util.headerItemClassName,
10109 authorityIn => ame_util.postApprover);
10110 engInsertedApproverList(i).action_type_order_number := getNullActionTypeOrderNumber;
10111 engInsertedApproverList(i).group_or_chain_order_number := 1;
10112 end if;
10113 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
10114 fnd_log.string
10115 (fnd_log.level_statement
10116 ,'ame_engine.processAdhocInsertions'
10117 ,'Adhoc Insertion approver(absolute order) ::: ' || engInsertedApproverList(i).name
10118 );
10119 end if;
10120 insertApprover(indexIn => tempIndex,
10121 approverIn => engInsertedApproverList(i),
10122 adjustMemberOrderNumbersIn => true,
10123 inserteeIndexIn => i,
10124 currentInsIndex => i);
10125 populateInsertionIndexes(indexIn => tempIndex
10126 ,insertionOrderIn => engInsertionOrderList(i));
10127 engStApproversCount := engStApproversCount + 1;
10128 /* afterApprover, beforeApprover */
10129 elsif(engInsertionOrderTypeList(i) in (ame_util.afterApprover,
10130 ame_util.beforeApprover)) then
10131 tempIndex := 1; /* post-increment */
10132 loop
10133 tempBoolean := false;
10134 /*
10135 In this loop, tempBoolean indicates whether engStApprovers(tempIndex) matches
10136 the insertion parameter.
10137 */
10138 if(engStApprovers(tempIndex).name = parameterFields(1) and
10139 engStApprovers(tempIndex).occurrence = parameterFields(6) and
10140 engStApprovers(tempIndex).group_or_chain_id = parameterFields(5) and
10141 engStApprovers(tempIndex).action_type_id = parameterFields(4) and
10142 engStApprovers(tempIndex).item_id = parameterFields(3) and
10143 engStApprovers(tempIndex).item_class = parameterFields(2)) then
10144 tempBoolean := true;
10145 if(engInsertionOrderTypeList(i) = ame_util.afterApprover) then
10146 tempIndex2 := tempIndex + 1;
10147 else
10148 tempIndex2 := tempIndex;
10149 end if;
10150 engInsertedApproverList(i).action_type_id := engStApprovers(tempIndex).action_type_id;
10151 engInsertedApproverList(i).group_or_chain_id := engStApprovers(tempIndex).group_or_chain_id;
10152 engInsertedApproverList(i).occurrence :=
10153 getHandlerOccurrence(nameIn => engInsertedApproverList(i).name,
10154 itemClassIn => engInsertedApproverList(i).item_class,
10155 itemIdIn => engInsertedApproverList(i).item_id,
10156 actionTypeIdIn => engInsertedApproverList(i).action_type_id,
10157 groupOrChainIdIn => engInsertedApproverList(i).group_or_chain_id);
10158 if(engInsertionIsSpecialForwardee(i) = ame_util.booleanTrue) then
10159 engInsertedApproverList(i).source := ame_util.specialForwardInsertion;
10160 else
10161 if(engInsertionOrderTypeList(i) = ame_util.afterApprover and
10162 engStApprovers(tempIndex).approval_status = ame_util.forwardStatus) then
10163 engInsertedApproverList(i).source := ame_util.forwardInsertion;
10164 elsif(engInsertionOrderTypeList(i) = ame_util.afterApprover and
10165 engStApprovers(tempIndex).approval_status = ame_util.approveAndForwardStatus) then
10166 engInsertedApproverList(i).source := ame_util.approveAndForwardInsertion;
10167 else
10168 engInsertedApproverList(i).source := ame_util.otherInsertion;
10169 end if;
10170 end if;
10171 engInsertedApproverList(i).item_class_order_number := engStApprovers(tempIndex).item_class_order_number;
10172 engInsertedApproverList(i).item_order_number := engStApprovers(tempIndex).item_order_number;
10173 engInsertedApproverList(i).sub_list_order_number := engStApprovers(tempIndex).sub_list_order_number;
10174 engInsertedApproverList(i).action_type_order_number := engStApprovers(tempIndex).action_type_order_number;
10175 engInsertedApproverList(i).group_or_chain_order_number :=
10176 engStApprovers(tempIndex).group_or_chain_order_number;
10177 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
10178 fnd_log.string
10179 (fnd_log.level_statement
10180 ,'ame_engine.processAdhocInsertions'
10181 ,'Adhoc Insertion approver(after/before approver) ::: ' || engInsertedApproverList(i).name
10182 );
10183 end if;
10184 insertApprover(indexIn => tempIndex2,
10185 approverIn => engInsertedApproverList(i),
10186 adjustMemberOrderNumbersIn => true,
10187 inserteeIndexIn => i,
10188 currentInsIndex => i);
10189 populateInsertionIndexes(indexIn => tempIndex2
10190 ,insertionOrderIn => engInsertionOrderList(i));
10191 engStApproversCount := engStApproversCount + 1;
10192 end if;
10193 if(tempBoolean or
10194 tempIndex = engStApproversCount) then
10195 exit;
10196 end if;
10197 tempIndex := tempIndex + 1;
10198 end loop;
10199 else /* first/last pre/post approver */
10200 /*
10201 The source, action_type_id, and group_or_chain_id fields are set in
10202 ame_api3.getAvailableInsertions for these order types.
10203 */
10204 if(engStApproversCount = 0) then
10205 /*
10206 The four first/last pre/post order types can only occur in an empty list if the insertion
10207 is for the header item. Treat any other case of these order types as displaced, here.
10208 In the code blocks below for these four order types, require that engStApproversCount > 0.
10209 */
10210 if(parameterFields(3) = ame_util.headerItemClassName and
10211 parameterFields(2) = engTransactionId) then
10212 engInsertedApproverList(i).occurrence := 1;
10213 engInsertedApproverList(i).item_class_order_number :=
10214 getItemClassOrderNumber(itemClassIdIn =>
10215 getItemClassId(itemClassNameIn => ame_util.headerItemClassName));
10216 engInsertedApproverList(i).item_order_number := 1;
10217 engInsertedApproverList(i).sub_list_order_number :=
10218 getSublistOrderNum(itemClassNameIn => ame_util.headerItemClassName,
10219 authorityIn => engInsertedApproverList(i).authority);
10220 engInsertedApproverList(i).action_type_order_number := getNullActionTypeOrderNumber;
10221 engInsertedApproverList(i).group_or_chain_order_number := 1;
10222 engInsertedApproverList(i).member_order_number := 1;
10223 insertApprover(indexIn => 1,
10224 approverIn => engInsertedApproverList(i),
10225 adjustMemberOrderNumbersIn => false,
10226 inserteeIndexIn => i,
10227 currentInsIndex => i);
10228 populateInsertionIndexes(indexIn => 1
10229 ,insertionOrderIn => engInsertionOrderList(i));
10230 engStApproversCount := 1;
10231 else /* displaced */
10232 engInsertedApproverList(i).occurrence := 1;
10233 engInsertedApproverList(i).item_class_order_number :=
10234 getItemClassOrderNumber(itemClassIdIn =>
10235 getItemClassId(itemClassNameIn => engInsertedApproverList(i).item_class));
10236 engInsertedApproverList(i).item_order_number := 1;
10237 engInsertedApproverList(i).sub_list_order_number :=
10238 getSublistOrderNum(itemClassNameIn => engInsertedApproverList(i).item_class,
10239 authorityIn => engInsertedApproverList(i).authority);
10240 engInsertedApproverList(i).action_type_order_number := getNullActionTypeOrderNumber;
10241 engInsertedApproverList(i).group_or_chain_order_number := 1;
10242 engInsertedApproverList(i).member_order_number := 1;
10243 displacedInserteeIndexes(displacedInserteeIndexes.count + 1) := i;
10244 end if;
10245 else
10246 tempIndex := null;
10247 tempAnchorIndex := null;
10248 /* firstPostApprover */
10249 if(engInsertionOrderTypeList(i) = ame_util.firstPostApprover) then
10250 /*
10251 Insert at tempIndex if it's non-null, after checking the possible cases.
10252 Recall that the case where engStApproversCount = 0 is handled at the
10253 start of the procedure, that the item id is in parameterFields(3), and
10254 that the item-class ID is in parameterFields(2). Here are the cases
10255 requiring insertion (always at j + 1).
10256 1. j = 0,
10257 post-approver for the right item at j + 1 = 1
10258 2. j > 0,
10259 j < engStApproversCount,
10260 non-post-approver for the right item at j,
10261 post-approver for the right item at j + 1
10262 3. j > 0,
10263 j < engStApproversCount,
10264 non-post-approver for the right item at j,
10265 any approver for the wrong item at j + 1
10266 4. j > 0,
10267 j = engStApproversCount,
10268 non-post-approver for the right item at j
10269 5. j > 0,
10270 j < engStApproversCount,
10271 any approver for the wrong item at j,
10272 post-approver for the right item at j + 1
10273 Finally, note that the way the code is written, case 4 must be checked
10274 before cases 2, 3, and 5, to ensure that for these cases,
10275 j + 1 <= engStApproversCount.
10276 */
10277 /* The zero lower limit is intentional. */
10278 for j in 0 .. engStApproversCount loop
10279 tempIndex2 := j + 1;
10280 if(j = 0) then /* case 1 */
10281 if(engStApprovers(tempIndex2).authority = ame_util.postApprover and
10282 engStApprovers(tempIndex2).item_id = parameterFields(3) and
10283 engStApprovers(tempIndex2).item_class = parameterFields(2)) then
10284 tempIndex := tempIndex2;
10285 tempAnchorIndex := tempIndex2;
10286 exit;
10287 end if;
10288 else /* j > 0: cases 2-5 */
10289 /*
10290 non-post-approver for the right item at j: cases 2-4
10291 Case 4 comes before the others to prevent indexing into a non-existent
10292 engStApprovers(tempIndex2) when j = engStApproversCount.
10293 */
10294 if(engStApprovers(j).authority <> ame_util.postApprover and
10295 engStApprovers(j).item_id = parameterFields(3) and
10296 engStApprovers(j).item_class = parameterFields(2)) then
10297 if(j = engStApproversCount) then /* case 4 */
10298 tempIndex := tempIndex2;
10299 exit;
10300 end if;
10301 if(engStApprovers(tempIndex2).authority = ame_util.postApprover and
10302 engStApprovers(tempIndex2).item_id = parameterFields(3) and
10303 engStApprovers(tempIndex2).item_class = parameterFields(2)) then /* case 2 */
10304 tempIndex := tempIndex2;
10305 tempAnchorIndex := tempIndex2;
10306 exit;
10307 end if;
10308 if(engStApprovers(tempIndex2).item_id <> parameterFields(3) or
10309 engStApprovers(tempIndex2).item_class <> parameterFields(2)) then /* case 3 */
10310 tempIndex := tempIndex2;
10311 exit;
10312 end if;
10313 if((engStApprovers(j).item_id <> parameterFields(3) or
10314 engStApprovers(j).item_class <> parameterFields(2)) and
10315 engStApprovers(tempIndex2).authority = ame_util.postApprover and
10316 engStApprovers(tempIndex2).item_id = parameterFields(3) and
10317 engStApprovers(tempIndex2).item_class = parameterFields(2)) then /* case 5 */
10318 tempIndex := tempIndex2;
10319 tempAnchorIndex := tempIndex2;
10320 exit;
10321 end if;
10322 end if;
10323 end if;
10324 end loop;
10325 /* firstPreApprover */
10326 elsif(engInsertionOrderTypeList(i) = ame_util.firstPreApprover) then
10327 /*
10328 Insert at tempIndex if it's non-null, after checking the possible cases.
10329 Recall that the case where engStApproversCount = 0 is handled at the
10330 start of the procedure. Here are the cases requiring insertion (always
10331 at j).
10332 1. j = 1,
10333 any approver for the right item at j = 1
10334 2. j > 1,
10335 any approver for the wrong item at j - 1,
10336 any approver for the right item at j
10337 */
10338 for j in 1 .. engStApproversCount loop
10339 if(j = 1) then
10340 if(engStApprovers(1).item_id = parameterFields(3) and
10341 engStApprovers(1).item_class = parameterFields(2)) then /* case 1 */
10342 tempIndex := 1;
10343 if(engStApprovers(1).authority = ame_util.preApprover) then
10344 tempAnchorIndex := 1;
10345 end if;
10346 exit;
10347 end if;
10348 elsif((engStApprovers(j - 1).item_id <> parameterFields(3) or
10349 engStApprovers(j - 1).item_class <> parameterFields(2)) and
10350 engStApprovers(j).item_id = parameterFields(3) and
10351 engStApprovers(j).item_class = parameterFields(2)) then /* case 2 */
10352 tempIndex := j;
10353 if(engStApprovers(j).authority = ame_util.preApprover) then
10354 tempAnchorIndex := j;
10355 end if;
10356 exit;
10357 end if;
10358 end loop;
10359 /* lastPostApprover */
10360 elsif(engInsertionOrderTypeList(i) = ame_util.lastPostApprover) then
10361 /*
10362 Insert at tempIndex if it's non-null, after checking the possible cases.
10363 Recall that the case where engStApproversCount = 0 is handled at the
10364 start of the procedure. Here are the cases requiring insertion (always
10365 at j + 1).
10366 1. j = engStApproversCount,
10367 any approver for the right item at j
10368 2. j < engStApproversCount,
10369 any approver for right item at j,
10370 any approver for wrong item at j + 1
10371 */
10372 for j in 1 .. engStApproversCount loop
10373 if(j = engStApproversCount) then
10374 if(engStApprovers(j).item_id = parameterFields(3) and
10375 engStApprovers(j).item_class = parameterFields(2)) then
10376 tempIndex := engStApproversCount + 1;
10377 if(engStApprovers(j).authority = ame_util.postApprover) then
10378 tempAnchorIndex := j;
10379 end if;
10380 exit;
10381 end if;
10382 else
10383 if(engStApprovers(j).item_id = parameterFields(3) and
10384 engStApprovers(j).item_class = parameterFields(2) and
10385 (engStApprovers(j + 1).item_id <> parameterFields(3) or
10386 engStApprovers(j + 1).item_class <> parameterFields(2))) then
10387 tempIndex := j + 1;
10388 if(engStApprovers(j).authority = ame_util.postApprover) then
10389 tempAnchorIndex := j;
10390 end if;
10391 exit;
10392 end if;
10393 end if;
10394 end loop;
10395 /* lastPreApprover */
10396 else /* engInsertionOrderTypeList(i) = ame_util.lastPreApprover */
10397 /*
10398 Insert at tempIndex if it's non-null, after checking the possible cases.
10399 Recall that the case where engStApproversCount = 0 is handled at the
10400 start of the procedure. Here are the cases (always inserting at j):
10401 1. j = 1,
10402 non-pre-approver for the right item at 1
10403 2. j > 1,
10404 j <= engStApproversCount,
10405 the approver at j - 1 is for the right item,
10406 the approver at j is for the right item,
10407 the approver at j - 1 is a pre-approver,
10408 the approver at j is not a pre-approver
10409 3. j > 1,
10410 j <= engStApproversCount,
10411 any approver at j - 1 for the wrong item,
10412 the approver at j is for the right item,
10413 the approver at j is not a pre-approver
10414 */
10415 for j in 1 .. engStApproversCount loop
10416 if(j = 1) then
10417 if(engStApprovers(1).item_id = parameterFields(3) and
10418 engStApprovers(1).item_class = parameterFields(2) and
10419 engStApprovers(1).authority <> ame_util.preApprover) then /* case 1 */
10420 tempIndex := 1;
10421 exit;
10422 end if;
10423 else
10424 if(engStApprovers(j).item_id = parameterFields(3) and
10425 engStApprovers(j).item_class = parameterFields(2) and
10426 engStApprovers(j).authority <> ame_util.preApprover) then
10427 if(engStApprovers(j - 1).item_id = parameterFields(3) and
10428 engStApprovers(j - 1).item_class = parameterFields(2)) then
10429 if(engStApprovers(j - 1).authority = ame_util.preApprover) then /* case 2 */
10430 tempIndex := j;
10431 tempAnchorIndex := j - 1;
10432 exit;
10433 end if;
10434 else /* case 3 */
10435 tempIndex := j;
10436 exit;
10437 end if;
10438 end if;
10439 end if;
10440 end loop;
10441 end if;
10442 /* Set the remaining fields in the insertee's approverRecord2. */
10443 engInsertedApproverList(i).source := ame_util.otherInsertion;
10444 if(tempAnchorIndex is null) then
10445 engInsertedApproverList(i).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
10446 /* This code was commented out to fix BUG (4095846) */
10447 /* Issue 9 in the list of bugs identified during implementation of */
10448 /* asynchronous parallel approver functionality */
10449 /* engInsertedApproverList(i).action_type_id := ame_util.nullInsertionActionTypeId; */
10450 engInsertedApproverList(i).occurrence :=
10451 getHandlerOccurrence(nameIn => engInsertedApproverList(i).name,
10452 itemClassIn => engInsertedApproverList(i).item_class,
10453 itemIdIn => engInsertedApproverList(i).item_id,
10454 actionTypeIdIn => engInsertedApproverList(i).action_type_id,
10455 groupOrChainIdIn => engInsertedApproverList(i).group_or_chain_id);
10456 engInsertedApproverList(i).item_class_order_number :=
10457 getItemClassOrderNumber(itemClassIdIn =>
10458 getItemClassId(itemClassNameIn => engInsertedApproverList(i).item_class));
10459 engInsertedApproverList(i).item_order_number :=
10460 getItemOrderNumber(itemClassNameIn => engInsertedApproverList(i).item_class,
10461 itemIdIn => engInsertedApproverList(i).item_id);
10462 /* Code Modified to fix BUG (4095825) */
10463 /* Issue 2 in the list of bugs identified during implementation of */
10464 /* asynchronous parallel approver functionality */
10465 if engInsertionOrderTypeList(i) = ame_util.firstPreApprover or
10466 engInsertionOrderTypeList(i) = ame_util.lastPreApprover then
10467 engInsertedApproverList(i).sub_list_order_number :=
10468 getSublistOrderNum(itemClassNameIn => engInsertedApproverList(i).item_class,
10469 authorityIn => ame_util.preApprover);
10470 elsif engInsertionOrderTypeList(i) = ame_util.firstPostApprover or
10471 engInsertionOrderTypeList(i) = ame_util.lastPostApprover then
10472 engInsertedApproverList(i).sub_list_order_number :=
10473 getSublistOrderNum(itemClassNameIn => engInsertedApproverList(i).item_class,
10474 authorityIn => ame_util.postApprover);
10475 end if;
10476 /* Code Modified to fix BUG (4095846) */
10477 /* Issue 9 in the list of bugs identified during implementation of */
10478 /* asynchronous parallel approver functionality */
10479 /* engInsertedApproverList(i).action_type_order_number := getNullActionTypeOrderNumber; */
10480 engInsertedApproverList(i).action_type_order_number := 1;
10481 engInsertedApproverList(i).group_or_chain_order_number := 1;
10482 else
10483 engInsertedApproverList(i).group_or_chain_id := ame_util.nullInsertionGroupOrChainId;
10484 /* Code Modified to fix BUG (4095846) */
10485 /* Issue 9 in the list of bugs identified during implementation of */
10486 /* asynchronous parallel approver functionality */
10487 /* engInsertedApproverList(i).action_type_id := ame_util.nullInsertionActionTypeId;*/
10488 engInsertedApproverList(i).occurrence :=
10489 getHandlerOccurrence(nameIn => engInsertedApproverList(i).name,
10490 itemClassIn => engInsertedApproverList(i).item_class,
10491 itemIdIn => engInsertedApproverList(i).item_id,
10492 actionTypeIdIn => engInsertedApproverList(i).action_type_id,
10493 groupOrChainIdIn => engInsertedApproverList(i).group_or_chain_id);
10494 engInsertedApproverList(i).item_class_order_number :=
10495 engStApprovers(tempAnchorIndex).item_class_order_number;
10496 engInsertedApproverList(i).item_order_number :=
10497 engStApprovers(tempAnchorIndex).item_order_number;
10498 engInsertedApproverList(i).sub_list_order_number :=
10499 engStApprovers(tempAnchorIndex).sub_list_order_number;
10500 /* Code Modified to fix BUG (4095846) */
10501 /* Issue 9 in the list of bugs identified during implementation of */
10502 /* asynchronous parallel approver functionality */
10503 /*engInsertedApproverList(i).action_type_order_number := */
10504 /* engStApprovers(tempAnchorIndex).action_type_order_number; */
10505 if engInsertionOrderTypeList(i) = ame_util.firstPreApprover or
10506 engInsertionOrderTypeList(i) = ame_util.firstPostApprover then
10507 engInsertedApproverList(i).action_type_order_number :=
10508 engStApprovers(tempAnchorIndex).action_type_order_number - 1;
10509 elsif engInsertionOrderTypeList(i) = ame_util.lastPreApprover or
10510 engInsertionOrderTypeList(i) = ame_util.lastPostApprover then
10511 engInsertedApproverList(i).action_type_order_number :=
10512 engStApprovers(tempAnchorIndex).action_type_order_number + 1;
10513 end if;
10514 engInsertedApproverList(i).group_or_chain_order_number :=
10515 engStApprovers(tempAnchorIndex).group_or_chain_order_number;
10516 end if;
10517 /* Perform the insertion if the proper position has been located. */
10518 if(tempIndex is null) then
10519 displacedInserteeIndexes(displacedInserteeIndexes.count + 1) := i;
10520 else
10521 /* Code Modified to fix BUG (4095846) */
10522 /* Issue 9 in the list of bugs identified during implementation of */
10523 /* asynchronous parallel approver functionality */
10524 if engInsertionOrderTypeList(i) = ame_util.firstPreApprover or
10525 engInsertionOrderTypeList(i) = ame_util.firstPostApprover then
10526 engInsertedApproverList(i).action_type_id := -1;
10527 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
10528 fnd_log.string
10529 (fnd_log.level_statement
10530 ,'ame_engine.processAdhocInsertions'
10531 ,'Adhoc Insertion approver(first pre/first post approver) ::: ' || engInsertedApproverList(i).name
10532 );
10533 end if;
10534 insertApprover(indexIn => tempIndex,
10535 approverIn => engInsertedApproverList(i),
10536 adjustMemberOrderNumbersIn => true,
10537 approverLocationIn => ame_util.firstAmongEquals,
10538 inserteeIndexIn => i,
10539 currentInsIndex => i);
10540 populateInsertionIndexes(indexIn => tempIndex
10541 ,insertionOrderIn => engInsertionOrderList(i));
10542 elsif engInsertionOrderTypeList(i) = ame_util.lastPreApprover or
10543 engInsertionOrderTypeList(i) = ame_util.lastPostApprover then
10544 engInsertedApproverList(i).action_type_id := -2;
10545 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
10546 fnd_log.string
10547 (fnd_log.level_statement
10548 ,'ame_engine.processAdhocInsertions'
10549 ,'Adhoc Insertion approver(last pre/last post approver) ::: ' || engInsertedApproverList(i).name
10550 );
10551 end if;
10552 insertApprover(indexIn => tempIndex,
10553 approverIn => engInsertedApproverList(i),
10554 adjustMemberOrderNumbersIn => true,
10555 approverLocationIn => ame_util.lastAmongEquals,
10556 inserteeIndexIn => i,
10557 currentInsIndex => i);
10558 populateInsertionIndexes(indexIn => tempIndex
10559 ,insertionOrderIn => engInsertionOrderList(i));
10560 end if;
10561 engStApproversCount := engStApproversCount + 1;
10562 end if;
10563 end if;
10564 end if;
10565 end if;
10566 end loop;
10567 /*
10568 Insert any displaced approvers at the end of their items' lists, if possible; and
10569 otherwise at the end of the transaction's list.
10570 */
10571 for i in 1 .. displacedInserteeIndexes.count loop
10572 parameterFields.delete;
10573 parseFields(stringIn => engInsertionParameterList(displacedInserteeIndexes(i)),
10574 fieldsOut => parameterFields);
10575 /* Set tempBoolean false if displaced approver i is inserted at the end of its item's list. */
10576 tempBoolean := true;
10577 engStApproversCount := engStApprovers.count;
10578 for j in 1 .. engStApproversCount loop
10579 if(engStApprovers(j).item_id = parameterFields(2) and
10580 engStApprovers(j).item_class = parameterFields(3) and
10581 (j = engStApproversCount or
10582 engStApprovers(j + 1).item_id <> parameterFields(2) or
10583 engStApprovers(j + 1).item_class <> parameterFields(3))) then
10584 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
10585 fnd_log.string
10586 (fnd_log.level_statement
10587 ,'ame_engine.processAdhocInsertions'
10588 ,'Adhoc Insertion approver(displaced) ::: ' || engInsertedApproverList(displacedInserteeIndexes(i)).name
10589 );
10590 end if;
10591 insertApprover(indexIn => j + 1,
10592 approverIn => engInsertedApproverList(displacedInserteeIndexes(i)),
10593 adjustMemberOrderNumbersIn => true,
10594 inserteeIndexIn => i,
10595 currentInsIndex => i);
10596 populateInsertionIndexes(indexIn => j + 1
10597 ,insertionOrderIn => engInsertionOrderList(displacedInserteeIndexes(i)));
10598 tempBoolean := false;
10599 exit;
10600 end if;
10601 end loop;
10602 if(tempBoolean) then
10603 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
10604 fnd_log.string
10605 (fnd_log.level_statement
10606 ,'ame_engine.processAdhocInsertions'
10607 ,'Adhoc Insertion approver(displaced) ::: ' || engInsertedApproverList(displacedInserteeIndexes(i)).name
10608 );
10609 end if;
10610 insertApprover(indexIn => engStApproversCount + 1,
10611 approverIn => engInsertedApproverList(displacedInserteeIndexes(i)),
10612 adjustMemberOrderNumbersIn => false,
10613 inserteeIndexIn => i,
10614 currentInsIndex => i);
10615 populateInsertionIndexes(indexIn => engStApproversCount + 1
10616 ,insertionOrderIn => engInsertionOrderList(displacedInserteeIndexes(i)));
10617 end if;
10618 engStApproversCount := engStApproversCount + 1;
10619 end loop;
10620 for i in reverse 1..engStApprovers.count loop
10621 if engStApprovers(i).orig_system = 'AME_INS_ORIG_SYSTEM' then
10622 for j in i+1..engStApprovers.count loop
10623 engStApprovers(j-1) := engStApprovers(j);
10624 end loop;
10625 engStApprovers.delete(engStApprovers.count);
10626 end if;
10627 end loop;
10628 exception
10629 when others then
10630 ame_util.runtimeException(packageNameIn => 'ame_engine',
10631 routineNameIn => 'processAdHocInsertions',
10632 exceptionNumberIn => sqlcode,
10633 exceptionStringIn => sqlerrm);
10634 raise;
10635 end processAdHocInsertions;
10636 --+
10637 --
10638 --+
10639 procedure getAllProductions(productionsOut out nocopy ame_util2.productionsTable) is
10640 begin
10641 for i in 1 .. engStProductionsTable.count loop
10642 productionsOut(i).variable_name := engStProductionsTable(i).variable_name;
10643 productionsOut(i).variable_value := engStProductionsTable(i).variable_value;
10644 productionsOut(i).item_class := engStProductionsTable(i).item_class;
10645 productionsOut(i).item_id := engStProductionsTable(i).item_id;
10646 end loop;
10647 end getAllProductions;
10648 procedure getProductions(itemClassIn in varchar2
10649 ,itemIdIn in varchar2
10650 ,productionsOut out nocopy ame_util2.productionsTable) is
10651 tempIndex integer;
10652 begin
10653 tempIndex := 1;
10654 for i in 1 .. engStProductionsTable.count loop
10655 if itemClassIn = engStProductionsTable(i).item_class and
10656 itemIdIn = engStProductionsTable(i).item_id then
10657 productionsOut(tempIndex).variable_name := engStProductionsTable(i).variable_name;
10658 productionsOut(tempIndex).variable_value := engStProductionsTable(i).variable_value;
10659 productionsOut(tempIndex).item_class := engStProductionsTable(i).item_class;
10660 productionsOut(tempIndex).item_id := engStProductionsTable(i).item_id;
10661 tempIndex := tempIndex+1;
10662 end if;
10663 end loop;
10664 end getProductions;
10665 procedure processActionType as
10666 tempIndex integer;
10667 begin
10668 if(engAppRuleTypes(engAppHandlerFirstIndex) = ame_util.productionRuleType) then
10669 /*
10670 Copy item-level productions to the appropriate engStProductionsTable. Note that we
10671 have to initialize tempIndex as below to account for the possibility of multiple
10672 production action types.
10673 */
10674 tempIndex := engStProductionsTable.count;
10675 for i in engAppHandlerFirstIndex .. engAppHandlerLastIndex loop
10676 tempIndex := tempIndex + 1;
10677 engStProductionsTable(tempIndex).variable_name := engAppParameters(i);
10678 engStProductionsTable(tempIndex).variable_value := engAppParameterTwos(i);
10679 engStProductionsTable(tempIndex).item_class := getHandlerItemClassName;
10680 engStProductionsTable(tempIndex).item_id := getHandlerItemId;
10681 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
10682 fnd_log.string
10683 (fnd_log.level_statement
10684 ,'ame_engine.processActionType'
10685 ,'Transaction Production ::: ' || engStProductionsTable(tempIndex).variable_name || '/' || engStProductionsTable(tempIndex).variable_value
10686 );
10687 end if;
10688 end loop;
10689 /*
10690 This elsif is necessary to avoid processing production actions of approver-generating rules.
10691 (The engine processes these after constructing the approver list.)
10692 */
10693 elsif(engActionTypeUsages(engAppActionTypeIds(engAppHandlerFirstIndex)) <>
10694 ame_util.productionRuleType) then
10695 /*
10696 Call the handler for action types other than the production-rule action type.
10697 (Per-approver productions get handled later.)
10698 */
10699 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
10700 fnd_log.string
10701 (fnd_log.level_statement
10702 ,'ame_engine.processActionType'
10703 ,'Processing Action Type ::: ' || engAppActionTypeIds(engAppHandlerFirstIndex)
10704 );
10705 end if;
10706 execute immediate
10707 'begin ' ||
10708 getActionTypePackageName(actionTypeIdIn => engAppActionTypeIds(engAppHandlerFirstIndex)) ||
10709 '.handler; end;';
10710 end if;
10711 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
10712 fnd_log.string
10713 (fnd_log.level_statement
10714 ,'ame_engine.processActionType'
10715 ,'Completed processing the action Type ::: ' || engAppActionTypeIds(engAppHandlerFirstIndex)
10716 );
10717 end if;
10718 exception
10719 when others then
10720 ame_util.runtimeException(packageNameIn => 'ame_engine',
10721 routineNameIn => 'processActionType',
10722 exceptionNumberIn => sqlcode,
10723 exceptionStringIn => sqlerrm);
10724 raise;
10725 end processActionType;
10726 procedure populateInsertionIndexes(indexIn in integer
10727 ,insertionOrderIn in integer) as
10728 firstIndex integer;
10729 lastIndex integer;
10730 tempValue integer;
10731 begin
10732 firstIndex := engStInsertionIndexes.first;
10733 if(engStInsertionIndexes.exists(firstIndex)) then
10734 lastIndex := engStInsertionIndexes.last;
10735 while engStInsertionIndexes.exists(lastIndex) and lastIndex >= indexIn loop
10736 tempValue := engStInsertionIndexes(lastIndex);
10737 engStInsertionIndexes(lastIndex + 1) := tempValue;
10738 engStInsertionIndexes.delete(lastIndex);
10739 lastIndex := engStInsertionIndexes.prior(lastIndex + 1);
10740 end loop;
10741 engStInsertionIndexes(indexIn) := insertionOrderIn;
10742 else
10743 engStInsertionIndexes(indexIn) := insertionOrderIn;
10744 end if;
10745 end populateInsertionIndexes;
10746 procedure processSuppressDeviation(approverIndexIn in number,suppressApproverIndex in number) as
10747 tempcount number;
10748 begin
10749 engDeviationResultList(approverIndexIn).effectiveDate := engSuppressionDateList(suppressApproverIndex);
10750 engDeviationResultList(approverIndexIn).reason := engSupperssionReasonList(suppressApproverIndex);
10751 exception
10752 when others then
10753 ame_util.runtimeException(packageNameIn => 'ame_engine',
10754 routineNameIn => 'processSuppressDeviation',
10755 exceptionNumberIn => sqlcode,
10756 exceptionStringIn => sqlerrm);
10757 end processSuppressDeviation;
10758 procedure processSuppressions as
10759 begin
10760 for i in 1 .. engDeletedApproverList.count loop
10761 for j in 1 .. engStApprovers.count loop
10762 if(engStApprovers(j).name = engDeletedApproverList(i).name and
10763 engStApprovers(j).occurrence = engDeletedApproverList(i).occurrence and
10764 engStApprovers(j).group_or_chain_id = engDeletedApproverList(i).group_or_chain_id and
10765 engStApprovers(j).action_type_id = engDeletedApproverList(i).action_type_id and
10766 engStApprovers(j).item_id = engDeletedApproverList(i).item_id and
10767 engStApprovers(j).item_class = engDeletedApproverList(i).item_class) then
10768 engStApprovers(j).approval_status := ame_util.suppressedStatus;
10769 engStApprovers(j).source := ame_util.apiSuppression;
10770 processSuppressDeviation(j,i);
10771 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
10772 fnd_log.string
10773 (fnd_log.level_statement
10774 ,'ame_engine.processSuppressions'
10775 ,'Suppressed approver ::: ' || engStApprovers(j).name
10776 );
10777 end if;
10778 end if;
10779 end loop;
10780 end loop;
10781 exception
10782 when others then
10783 ame_util.runtimeException(packageNameIn => 'ame_engine',
10784 routineNameIn => 'processSuppressions',
10785 exceptionNumberIn => sqlcode,
10786 exceptionStringIn => sqlerrm);
10787 raise;
10788 end processSuppressions;
10789 procedure processExceptions as
10790 authorityRuleSuppressed boolean;
10791 currentFirstAuthorityIndex integer;
10792 currentFirstExceptionIndex integer;
10793 currentFirstItemIndex integer;
10794 currentLastAuthorityIndex integer;
10795 currentLastExceptionIndex integer;
10796 currentLastItemIndex integer;
10797 currentItemClassId integer;
10798 currentItemId ame_util.stringType;
10799 ruleCount integer;
10800 tempAttributeId integer;
10801 tempAttributeIdsToMatch ame_util.idList;
10802 tempExcOrdCondAttributeIds ame_util.idList;
10803 tempBoolean boolean;
10804 tempBoolean2 boolean;
10805 begin
10806 /* Handle the empty-rule-list case first. */
10807 if(engAppRuleIds.count = 0) then
10808 return;
10809 end if;
10810 authorityRuleSuppressed := false;
10811 /* Check for exception rules. */
10812 ruleCount := engAppRuleIds.count; /* This value gets used later in the code too. */
10813 tempBoolean := true;
10814 for i in 1 .. ruleCount loop
10815 if(engAppRuleTypes(i) = ame_util.exceptionRuleType) then
10816 tempBoolean := false;
10817 exit;
10818 end if;
10819 end loop;
10820 if(tempBoolean) then /* No exception rules. */
10821 return;
10822 end if;
10823 /* Now handle the case of a nonempty rule list containing at least one exception rule. */
10824 currentLastItemIndex := 0; /* This will set currentFirstItemIndex to one below. */
10825 loop /* Loop through the sublists of rules applying to an item. */
10826 /* Initialize the current[whatever]Index values. */
10827 currentFirstItemIndex := currentLastItemIndex + 1;
10828 currentLastItemIndex := null;
10829 currentFirstAuthorityIndex := null;
10830 currentLastAuthorityIndex := null;
10831 currentFirstExceptionIndex := null;
10832 currentLastExceptionIndex := null;
10833 currentItemClassId := engAppRuleItemClassIds(currentFirstItemIndex);
10834 currentItemId := engAppAppItemIds(currentFirstItemIndex);
10835 /* Set the current[whatever]Index values. */
10836 for i in currentFirstItemIndex .. ruleCount loop
10837 if(currentItemClassId <> engAppRuleItemClassIds(i) or
10838 currentItemId <> engAppAppItemIds(i)) then
10839 currentLastItemIndex := i - 1;
10840 exit;
10841 elsif(i = ruleCount) then
10842 currentLastItemIndex := i;
10843 end if;
10844 if(engAppRuleTypes(i) = ame_util.authorityRuleType) then
10845 if(currentFirstAuthorityIndex is null) then
10846 currentFirstAuthorityIndex := i;
10847 end if;
10848 currentLastAuthorityIndex := i;
10849 elsif(engAppRuleTypes(i) = ame_util.exceptionRuleType) then
10850 if(currentFirstExceptionIndex is null) then
10851 currentFirstExceptionIndex := i;
10852 end if;
10853 currentLastExceptionIndex := i;
10854 end if;
10855 end loop;
10856 /* Process the current item's exception rules (if any). */
10857 if(currentFirstExceptionIndex is not null) then
10858 for i in currentFirstExceptionIndex .. currentLastExceptionIndex loop
10859 /*
10860 Build the list of attribute IDs for the ordinary conditions used by this exception
10861 (in the local variable tempExcOrdCondAttributeIds) by looping through the engACU variables
10862 until the current exception's rule ID is matched. Index the list of attribute IDs by
10863 attribute ID (the value doesn't matter, so we set it to a constant--one--for efficiency).
10864 Here tempBoolean indicates whether the exception rule has been found in the engACU
10865 variables, so we can exit the inner loop once we find all of the exception's attributes.
10866 */
10867 tempBoolean := false;
10868 tempExcOrdCondAttributeIds.delete;
10869 for j in 1 .. engACUsageRuleIds.count loop
10870 if(engACUsageRuleIds(j) = engAppRuleIds(i)) then
10871 tempBoolean := true;
10872 if(engACConditionTypes(engACUsageConditionIds(j)) = ame_util.ordinaryConditionType) then
10873 tempExcOrdCondAttributeIds(engACAttributeIds(engACUsageConditionIds(j))) := 1;
10874 end if;
10875 elsif(tempBoolean) then
10876 exit;
10877 end if;
10878 end loop;
10879 /* Suppress authority rules as necessary. */
10880 if(currentFirstAuthorityIndex is not null) then
10881 for j in currentFirstAuthorityIndex .. currentLastAuthorityIndex loop
10882 /* A previous iteration of the i loop could have suppressed the rule at j; check for this. */
10883 if(engAppRuleIds.exists(j)) then
10884 /*
10885 Rather than rebuild tempExcOrdCondAttributeIds at each iteration,
10886 copy it at each iteration, so we can freely delete entries in the
10887 copy.
10888 */
10889 tempAttributeIdsToMatch.delete;
10890 ame_util.copyIdList(idListIn => tempExcOrdCondAttributeIds,
10891 idListOut => tempAttributeIdsToMatch);
10892 /*
10893 For an applicable exception to override an otherwise applicable authority rule,
10894 both rules' ordinary conditions must be defined on the same attributes. (If
10895 neither rule has any ordinary conditions, the exception overrides the authority
10896 rule.) Here tempBoolean indicates whether each of the authority rule's
10897 attributes were matched, and tempBoolean2 indicates whether the target authority
10898 rule has been found in the engACU variables.
10899 */
10900 tempBoolean := true;
10901 tempBoolean2 := false;
10902 for k in 1 .. engACUsageRuleIds.count loop
10903 if(engACUsageRuleIds(k) = engAppRuleIds(j)) then
10904 tempBoolean2 := true;
10905 /*
10906 (An authority rule only has ordinary conditions, so we don't have to check
10907 the condition type here.)
10908 */
10909 tempAttributeId := engACAttributeIds(engACUsageConditionIds(k));
10910 if(tempAttributeIdsToMatch.exists(tempAttributeId)) then
10911 tempAttributeIdsToMatch.delete(tempAttributeId);
10912 else
10913 tempBoolean := false;
10914 exit;
10915 end if;
10916 elsif(tempBoolean2) then
10917 exit;
10918 end if;
10919 end loop;
10920 if(tempBoolean and
10921 tempAttributeIdsToMatch.count = 0) then
10922 /*
10923 All of the authority rule's conditions' attributes were matched, and all of the
10924 exception's ordinary conditions' attributes were matched; so, delete the authority
10925 rule from the list of applicable rules.
10926 */
10927 authorityRuleSuppressed := true;
10928 engAppItemClassIds.delete(j);
10929 engAppItemIds.delete(j);
10930 engAppRuleIds.delete(j);
10931 engRuleAppliedYN.delete(j);
10932 engAppRuleTypes.delete(j);
10933 engAppActionTypeIds.delete(j);
10934 engAppParameters.delete(j);
10935 engAppParameterTwos.delete(j);
10936 engAppRuleItemClassIds.delete(j);
10937 engAppAppItemIds.delete(j);
10938 end if;
10939 end if;
10940 end loop; /* j */
10941 end if;
10942 /*
10943 Convert the exception rule to an authority rule, so it gets processed with
10944 the remaining authority rules.
10945 */
10946 engAppRuleTypes(i) := ame_util.authorityRuleType;
10947 end loop;
10948 end if;
10949 /* Exit the outer loop if no more item rule lists exist. */
10950 if(currentLastItemIndex = ruleCount) then
10951 exit;
10952 end if;
10953 end loop;
10954 /* Re-compact the engApp lists if any authority rules got deleted. */
10955 if(authorityRuleSuppressed) then
10956 compactEngAppLists(compactPrioritiesIn => false,
10957 compactActionTypeIdsIn => true,
10958 compactParametersIn => true);
10959 end if;
10960 exception
10961 when others then
10962 ame_util.runtimeException(packageNameIn => 'ame_engine',
10963 routineNameIn => 'processExceptions',
10964 exceptionNumberIn => sqlcode,
10965 exceptionStringIn => sqlerrm);
10966 raise;
10967 end processExceptions;
10968 procedure processRepeatedApprovers as
10969 engAppRuleIdsCount integer;
10970 engStApproversCount integer;
10971 productionActionTypeId integer;
10972 repeatedApproversMode ame_util.attributeValueType;
10973 repeatedByApproverIndex integer;
10974 repeatedIndexesList ame_util.idList;
10975 tempAuthority ame_util.charType;
10976 tempActionTypeId integer;
10977 tempCount integer;
10978 tempEngStItemIndex integer;
10979 tempEngStProductionIndex integer;
10980 tempEngStRuleIndex integer;
10981 tempFirstIndexOfLastItem integer;
10982 tempFirstOccurrenceCurGrouping integer;
10983 tempGroupOrChainId integer;
10984 tempItemClass ame_util.stringType;
10985 tempItemId ame_util.stringType;
10986 tempApproverCategory ame_util.charType;
10987 tempProcessApprover boolean;
10988 tempRuleNotFound boolean;
10989 tempRuleIdList ame_util.idList;
10990 tempRuleIdList2 ame_util.idList;
10991 tempSourceDescription ame_util.longStringType;
10992 treeLevel integer;
10993 tempRepeatedAprCount number;
10994 tempChangeStatus boolean;
10995 begin
10996 /*
10997 This procedure does two things: (1) suppress repeated approvers, and (2) aggregate various
10998 approver-related data in appropriate engSt package variables. The aggregation has to occur
10999 for all occurrences of a wf_roles.name value in engStApprovers, at once; so this procedure's
11000 outer loop iterates through engStApprovers, doing the aggregation. The inner loop suppresses
11001 repeated approvers.
11002 */
11003 tempEngStItemIndex := 0; /* pre-increment */
11004 tempEngStProductionIndex := 0; /* pre-increment */
11005 tempEngStRuleIndex := 0; /* pre-increment */
11006 repeatedApproversMode := getConfigVarValue(configVarNameIn => ame_util.repeatedApproverConfigVar);
11007 /* Set treeLevel for efficiency in the inner loop. */
11008 if(repeatedApproversMode = ame_util.oncePerTransaction) then
11009 treeLevel := 0;
11010 elsif(repeatedApproversMode = ame_util.oncePerItemClass) then
11011 treeLevel := 1;
11012 elsif(repeatedApproversMode = ame_util.oncePerItem) then
11013 treeLevel := 2;
11014 elsif(repeatedApproversMode = ame_util.oncePerSublist) then
11015 treeLevel := 3;
11016 elsif(repeatedApproversMode = ame_util.oncePerActionType) then
11017 treeLevel := 4;
11018 elsif(repeatedApproversMode = ame_util.oncePerGroupOrChain) then
11019 treeLevel := 5;
11020 else /* repeatedApproversMode = ame_util.eachOccurrence */
11021 treeLevel := 6;
11022 end if;
11023 engStApproversCount := engStApprovers.count;
11024 for i in 1 .. engStApproversCount loop
11025 /*
11026 We only want to process an approver if the approver has not been previously processed and
11027 has not been suppressed. If an approver was suppressed, they can't aggregate the approvals
11028 requirements of subsequent occurrences of the same wf_roles.name in engStApprovers. If an
11029 approver was previously processed, we don't want to duplicate their data in the engStItem
11030 variables.
11031 */
11032 tempProcessApprover := true;
11033 if(engStApprovers(i).approval_status in (ame_util.suppressedStatus
11034 ,ame_util.repeatedStatus)) then
11035 tempProcessApprover := false;
11036 else
11037 for j in 1 .. (i - 1) loop
11038 if(engStApprovers(j).name = engStApprovers(i).name and
11039 engStApprovers(j).approver_category = engStApprovers(i).approver_category) then
11040 tempProcessApprover := false;
11041 exit;
11042 end if;
11043 end loop;
11044 end if;
11045 if(tempProcessApprover) then
11046 /*
11047 Iterate through the rest of the approver list, looking for engStApprovers(i).name, and outputting
11048 each occurrence's data as required to various engSt variables. If engStApprovers(i).name has
11049 already occurred in the current grouping, set engStApprovers(i).approval_status to
11050 ame_util.repeatedStatus and output its data for the index tempFirstOccurrenceCurGrouping.
11051 Otherwise output its data for index j. (Set tempFirstOccurrenceCurGrouping to j when we find a
11052 new repeated-approvers grouping.)
11053 */
11054 for j in i .. engStApproversCount loop
11055 if(engStApprovers(j).name = engStApprovers(i).name and
11056 engStApprovers(j).approver_category = engStApprovers(i).approver_category) then
11057 /*
11058 If repeatedApproversMode is ame_util.oncePerTransaction (that is, treeLevel = 6),
11059 all occurrences of the approver with j > i are repeated.
11060 */
11061 if(j = i or
11062 treeLevel = 6 or
11063 (treelevel = 5 and tempGroupOrChainId <> engStApprovers(j).group_or_chain_id) or
11064 (treeLevel > 3 and tempActionTypeId <> engStApprovers(j).action_type_id) or
11065 (treeLevel > 2 and tempAuthority <> engStApprovers(j).authority) or
11066 (treeLevel > 1 and tempItemId <> engStApprovers(j).item_id) or
11067 (treeLevel > 0 and tempItemClass <> engStApprovers(j).item_class)) then
11068 /* We're in a new repeatedApprovers grouping. */
11069 tempFirstOccurrenceCurGrouping := j;
11070 tempGroupOrChainId := engStApprovers(j).group_or_chain_id;
11071 tempActionTypeId := engStApprovers(j).action_type_id;
11072 tempAuthority := engStApprovers(j).authority;
11073 tempItemId := engStApprovers(j).item_id;
11074 tempItemClass := engStApprovers(j).item_class;
11075 repeatedIndexesList(1) := j;
11076 else /* This is a repeated approver. */
11077 /*
11078 Don't overwrite non-null statuses with ame_util.repeatedStatus. These can reflect
11079 per-item approver responses. See the ame_api2.updateApprovalStatus code for details.
11080 Also, don't suppress special forwardees. See bug 3401298 for details.
11081 */
11082 if(engStApprovers(j).approval_status is null and
11083 engStApprovers(j).source not like ame_util.specialForwardInsertion || '%') then
11084 engStApprovers(j).approval_status := ame_util.repeatedStatus;
11085 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
11086 fnd_log.string
11087 (fnd_log.level_statement
11088 ,'ame_engine.processRepeatedApprovers'
11089 ,'Repeated Approver ::: ' || engStApprovers(j).name
11090 );
11091 end if;
11092 end if;
11093 if engStApprovers(j).approval_status in (ame_util.repeatedStatus
11094 ,ame_util.notifiedByRepeatedStatus
11095 ,ame_util.approvedByRepeatedStatus
11096 ,ame_util.rejectedByRepeatedStatus
11097 ,ame_util.rejectStatus
11098 ,ame_util.approvedStatus
11099 ,ame_util.notifiedStatus
11100 ,ame_util.beatByFirstResponderStatus) then
11101 /* Get the repeated by approver's tree node index */
11102 repeatedIndexesList(repeatedIndexesList.count + 1) := j;
11103 end if;
11104 end if;
11105 end if;
11106 end loop;
11107 tempCount := engStRepeatedIndexes.count;
11108 if repeatedIndexesList.count > 1 then
11109 for x in 1 .. repeatedIndexesList.count loop
11110 for y in 1 .. repeatedIndexesList.count loop
11111 tempCount := tempCount + 1;
11112 engStRepeatedIndexes(tempCount) := repeatedIndexesList(x);
11113 engStRepeatedAppIndexes(tempCount) := repeatedIndexesList(y);
11114 end loop;
11115 end loop;
11116 end if;
11117 repeatedIndexesList.delete;
11118 end if;
11119 end loop;
11120 -- Handle the case of migration from pre ASP to ASP.
11121 for i in 1 .. engStApprovers.count loop
11122 for j in 1 .. engStRepeatedIndexes.count loop
11123 if engStRepeatedIndexes(j) = i and engStRepeatedAppIndexes(j) <> i then
11124 if engStApprovers(i).approval_status = ame_util.repeatedStatus or
11125 engStApprovers(i).approval_status is null then
11126 if engStApprovers(engStRepeatedAppIndexes(j)).approval_status = ame_util.approvedStatus then
11127 engStApprovers(i).approval_status := ame_util.approvedByRepeatedStatus;
11128 elsif engStApprovers(engStRepeatedAppIndexes(j)).approval_status
11129 = ame_util.noResponseStatus then
11130 engStApprovers(i).approval_status := ame_util2.noResponseByRepeatedStatus;
11131 elsif engStApprovers(engStRepeatedAppIndexes(j)).approval_status
11132 = ame_util.notifiedStatus then
11133 engStApprovers(i).approval_status := ame_util.notifiedByRepeatedStatus;
11134 elsif engStApprovers(engStRepeatedAppIndexes(j)).approval_status
11135 = ame_util.forwardStatus then
11136 engStApprovers(i).approval_status := ame_util2.forwardByRepeatedStatus;
11137 end if;
11138 end if;
11139 end if;
11140 end loop;
11141 end loop;
11142 -- handle the repetaed status case
11143 tempRepeatedAprCount := engStRepeatedIndexes.count;
11144 for i in 1..engStApprovers.count loop
11145 if engStApprovers(i).approval_status in (ame_util.notifiedByRepeatedStatus
11146 ) then
11147 if tempRepeatedAprCount = 0 then
11148 if engStApprovers(i).approval_status = ame_util.notifiedByRepeatedStatus then
11149 engStApprovers(i).approval_status := ame_util.notifiedStatus ;
11150 end if;
11151 end if;
11152 tempChangeStatus := true;
11153 for j in 1..tempRepeatedAprCount loop
11154 if engStRepeatedIndexes(j) = i and engStRepeatedAppIndexes(j) <> i then
11155 if engStApprovers(engStRepeatedAppIndexes(j)).approval_status is null or
11156 (engStApprovers(engStRepeatedAppIndexes(j)).approval_status = ame_util.notifiedStatus
11157 and engStApprovers(i).approval_status = ame_util.notifiedByRepeatedStatus ) then
11158 tempChangeStatus := false;
11159 exit;
11160 end if;
11161 end if;
11162 end loop;
11163 if tempChangeStatus then
11164 if engStApprovers(i).approval_status = ame_util.notifiedByRepeatedStatus then
11165 engStApprovers(i).approval_status := null ;
11166 end if;
11167 end if;
11168 end if;
11169 end loop;
11170 exception
11171 when others then
11172 ame_util.runtimeException(packageNameIn => 'ame_engine',
11173 routineNameIn => 'processRepeatedApprovers',
11174 exceptionNumberIn => sqlcode,
11175 exceptionStringIn => sqlerrm);
11176 raise;
11177 end processRepeatedApprovers;
11178 procedure processRules(processOnlyProductionsIn in boolean default false) as
11179 currentActionTypeId integer;
11180 currentFirstItemIndex integer;
11181 currentFirstRuleIndexes ame_util.idList; /* indexed by rule type */
11182 currentIndex integer;
11183 currentItemClassId integer;
11184 currentItemId ame_util.stringType;
11185 currentLastItemIndex integer;
11186 currentLastRuleIndexes ame_util.idList; /* indexed by rule type */
11187 currentRuleType integer;
11188 ruleCount integer;
11189 ruleTypes ame_util.idList;
11190 tempIndex integer;
11191 tempLastRuleIndex integer;
11192 tempRuleType integer;
11193 ruleTypeUpperLimit integer;
11194 begin
11195 /* Handle the empty-rule-list case first. */
11196 if(engAppRuleIds.count = 0) then
11197 return;
11198 end if;
11199 /* Now handle the nonempty-rule-list case. . . . */
11200 /*
11201 Set the order in which rule types are processed, for a given item.
11202 Combination rules have already been split into their single-action
11203 components, and exceptions have been converted into authority rules,
11204 so ignore these rule types.
11205 */
11206 ruleTypes(1) := ame_util.productionRuleType;
11207 ruleTypes(2) := ame_util.preListGroupRuleType;
11208 ruleTypes(3) := ame_util.authorityRuleType;
11209 ruleTypes(4) := ame_util.postListGroupRuleType;
11210 ruleTypes(5) := ame_util.listModRuleType;
11211 ruleTypes(6) := ame_util.substitutionRuleType;
11212 /* Initialize the engine substitution variables. */
11213 engAppSubHandlerFirstIndex := null;
11214 engAppSubHandlerLastIndex := null;
11215 /* Initialize the state variables. */
11216 ruleCount := engAppRuleIds.count;
11217 currentItemClassId := engAppRuleItemClassIds(1);
11218 currentItemId := engAppAppItemIds(1);
11219 currentRuleType := engAppRuleTypes(1);
11220 currentFirstItemIndex := 1;
11221 currentFirstRuleIndexes(currentRuleType) := 1;
11222 currentIndex := 2;
11223 /* Iterate through the items. */
11224 loop
11225 if(currentIndex > ruleCount or
11226 currentItemClassId <> engAppRuleItemClassIds(currentIndex) or
11227 currentItemId <> engAppAppItemIds(currentIndex)) then
11228 currentLastItemIndex := currentIndex - 1;
11229 currentLastRuleIndexes(currentRuleType) := currentLastItemIndex;
11230 elsif(currentRuleType <> engAppRuleTypes(currentIndex)) then
11231 currentLastRuleIndexes(currentRuleType) := currentIndex - 1;
11232 currentRuleType := engAppRuleTypes(currentIndex);
11233 currentFirstRuleIndexes(currentRuleType) := currentIndex;
11234 end if;
11235 if(currentLastItemIndex is not null) then
11236 /* Process the current item's rules. */
11237 if processOnlyProductionsIn then
11238 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
11239 fnd_log.string
11240 (fnd_log.level_statement
11241 ,'ame_engine.processRules'
11242 ,'Processing only production rules'
11243 );
11244 end if;
11245 ruleTypeUpperLimit := 1;
11246 else
11247 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
11248 fnd_log.string
11249 (fnd_log.level_statement
11250 ,'ame_engine.processRules'
11251 ,'Processing all rules'
11252 );
11253 end if;
11254 ruleTypeUpperLimit := 6;
11255 end if;
11256 for i in 1 .. ruleTypeUpperLimit loop
11257 /* Process the action types within rule type ruleTypes(i). */
11258 tempRuleType := ruleTypes(i);
11259 if(currentFirstRuleIndexes.exists(tempRuleType)) then
11260 /* Initialize the action-type state variables. */
11261 engAppHandlerFirstIndex := currentFirstRuleIndexes(tempRuleType);
11262 currentActionTypeId := engAppActionTypeIds(engAppHandlerFirstIndex);
11263 tempIndex := engAppHandlerFirstIndex + 1;
11264 tempLastRuleIndex := currentLastRuleIndexes(tempRuleType);
11265 loop
11266 if(tempIndex > tempLastRuleIndex or
11267 currentActionTypeId <> engAppActionTypeIds(tempIndex)) then
11268 /* Process the current action type for the current item. */
11269 engAppHandlerLastIndex := tempIndex - 1;
11270 processActionType;
11271 if (currentRuleType = ame_util.substitutionRuleType) then
11272 /* Set variables so subsequent call to the substitution handler is
11273 possible without iterating through the applicable rule list again */
11274 engAppSubHandlerFirstIndex :=currentFirstRuleIndexes(tempRuleType);
11275 engAppSubHandlerLastIndex := currentLastRuleIndexes(tempRuleType);
11276 end if;
11277 if(tempIndex <= tempLastRuleIndex) then
11278 /* Update the current action-type state variables. */
11279 engAppHandlerFirstIndex := tempIndex;
11280 currentActionTypeId := engAppActionTypeIds(tempIndex);
11281 end if;
11282 end if;
11283 /* Iterate or exit. */
11284 if(tempIndex > tempLastRuleIndex) then
11285 exit;
11286 end if;
11287 tempIndex := tempIndex + 1;
11288 end loop;
11289 end if;
11290 end loop;
11291 if(currentIndex <= ruleCount) then
11292 /* Update the current state variables. */
11293 currentFirstRuleIndexes.delete;
11294 currentLastRuleIndexes.delete;
11295 currentItemClassId := engAppRuleItemClassIds(currentIndex);
11296 currentItemId := engAppAppItemIds(currentIndex);
11297 currentRuleType := engAppRuleTypes(currentIndex);
11298 currentFirstItemIndex := currentIndex;
11299 currentFirstRuleIndexes(currentRuleType) := currentIndex;
11300 currentLastItemIndex := null;
11301 end if;
11302 end if;
11303 /* Iterate or exit. */
11304 if(currentIndex > ruleCount) then
11305 exit;
11306 end if;
11307 currentIndex := currentIndex + 1;
11308 end loop;
11309 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
11310 if engStApprovers.count = 0 then
11311 fnd_log.string
11312 (fnd_log.level_statement
11313 ,'ame_engine.processRules'
11314 ,'**************** No Approvers ******************'
11315 );
11316 else
11317 for i in 1 .. engStApprovers.count loop
11318 fnd_log.string
11319 (fnd_log.level_statement
11320 ,'ame_engine.processRules'
11321 ,'Approver ::: ' || engStApprovers(i).name
11322 );
11323 end loop;
11324 end if;
11325 end if;
11326 exception
11327 when others then
11328 ame_util.runtimeException(packageNameIn => 'ame_engine',
11329 routineNameIn => 'processRules',
11330 exceptionNumberIn => sqlcode,
11331 exceptionStringIn => sqlerrm);
11332 raise;
11333 end processRules;
11334 procedure processRelativePriorities as
11335 currentItemClassId integer;
11336 currentItemId ame_util.stringType;
11337 currentRuleType integer;
11338 currentThreshold integer;
11339 engAppRuleIdsCount integer;
11340 ruleDeleted boolean;
11341 tempAbsoluteThreshold integer;
11342 tempDoRelativePriorities boolean;
11343 tempFirstIndex integer;
11344 tempLastIndex integer;
11345 tempThresholdCounter integer;
11346 tempThresholds ame_util.idList;
11347 ruleExists boolean;
11348 tempIndex integer;
11349 oldTempIndex integer;
11350 begin
11351 /* Handle the trivial case here, so we can assume a non-empty applicable-rules list. */
11352 if(engAppRuleIds.count = 0) then
11353 return;
11354 end if;
11355 /* Now for the non-empty-list case. */
11356 ruleDeleted := false;
11357 /* Now for the non-empty-list case. */
11358 if engEvalPrioritiesPerItem then
11359 /* Evaluate priorites per item */
11360 tempFirstIndex := 1;
11361 engAppRuleIdsCount := engAppRuleIds.count;
11362 loop
11363 currentItemClassId := engAppRuleItemClassIds(tempFirstIndex);
11364 currentItemId := engAppAppItemIds(tempFirstIndex);
11365 currentRuleType := engAppRuleTypes(tempFirstIndex);
11366 tempThresholds.delete;
11367 tempLastIndex := null;
11368 tempDoRelativePriorities := engPriorityModes(currentRuleType) = ame_util.relativeRulePriority;
11369 /* Find tempLastIndex and optionally set the values in tempThresholds. */
11370 for i in tempFirstIndex .. engAppRuleIdsCount loop
11371 /* The following if does its comparisons in descending order of probability of success, for efficiency. */
11372 if(currentRuleType <> engAppRuleTypes(i) or
11373 currentItemId <> engAppAppItemIds(i) or
11374 currentItemClassId <> engAppRuleItemClassIds(i)) then
11375 tempLastIndex := i - 1;
11376 exit;
11377 else
11378 if(tempDoRelativePriorities) then
11379 /* The tempThresholds index and value are the same for convenience. */
11380 if engAppPriorities(i) is null then
11381 tempThresholds(99999) := engAppPriorities(i);
11382 else
11383 tempThresholds(engAppPriorities(i)) := engAppPriorities(i);
11384 end if;
11385 end if;
11386 end if;
11387 end loop;
11388 if(tempLastIndex is null) then
11389 tempLastIndex := engAppRuleIdsCount;
11390 end if;
11391 if(tempDoRelativePriorities) then
11392 /* Find the absolute threshold equivalent to the relative. */
11393 tempAbsoluteThreshold := tempThresholds.first;
11394 tempThresholdCounter := 1;
11395 currentThreshold := engPriorityThresholds(currentRuleType);
11396 while (tempThresholdCounter < currentThreshold) loop
11397 tempAbsoluteThreshold := tempThresholds.next(tempAbsoluteThreshold);
11398 tempThresholdCounter := tempThresholdCounter + 1;
11399 end loop;
11400 /* Do priority processing between tempFirstIndex and tempLastIndex. */
11401 for i in tempFirstIndex .. tempLastIndex loop
11402 if(engAppPriorities(i) is null or
11403 engAppPriorities(i) > tempAbsoluteThreshold) then
11404 engAppRuleIds.delete(i);
11405 engRuleAppliedYN.delete(i);
11406 engAppItemClassIds.delete(i);
11407 engAppItemIds.delete(i);
11408 engAppPriorities.delete(i);
11409 engAppApproverCategories.delete(i);
11410 engAppRuleTypes.delete(i);
11411 engAppRuleItemClassIds.delete(i);
11412 engAppAppItemIds.delete(i);
11413 ruleDeleted := true;
11414 end if;
11415 end loop;
11416 end if;
11417 /* If there are no more applicable rules to process, stop. */
11418 if(tempLastIndex = engAppRuleIdsCount) then
11419 exit;
11420 end if;
11421 tempFirstIndex := tempLastIndex + 1;
11422 end loop;
11423 else
11424 /* Evaluate priorities at transaction level */
11425 /* BUG Fixes : 4472308 and 4065967 */
11426 for i in 0 .. 7 loop
11427 tempDoRelativePriorities := engPriorityModes(i) = ame_util.relativeRulePriority;
11428 if tempDoRelativePriorities then
11429 ruleExists := false;
11430 tempIndex := engAppRuleIds.first;
11431 loop
11432 if engAppRuleTypes(tempIndex) = i then
11433 if engAppPriorities(tempIndex) is null then
11434 tempThresholds(99999) := engAppPriorities(tempIndex);
11435 else
11436 tempThresholds(engAppPriorities(tempIndex)) := engAppPriorities(tempIndex);
11437 end if;
11438 ruleExists := true;
11439 end if;
11440 tempIndex := engAppRuleIds.next(tempIndex);
11441 exit when tempIndex is null;
11442 end loop;
11443 if ruleExists then
11444 tempAbsoluteThreshold := tempThresholds.first;
11445 tempThresholdCounter := 1;
11446 currentThreshold := engPriorityThresholds(i);
11447 while (tempThresholdCounter < currentThreshold) loop
11448 tempAbsoluteThreshold := tempThresholds.next(tempAbsoluteThreshold);
11449 tempThresholdCounter := tempThresholdCounter + 1;
11450 end loop;
11451 tempIndex := engAppRuleIds.first;
11452 loop
11453 if(engAppRuleTypes(tempIndex) = i and
11454 (engAppPriorities(tempIndex) is null or
11455 engAppPriorities(tempIndex) > tempAbsoluteThreshold)) then
11456 oldTempIndex := tempIndex;
11457 tempIndex := engAppRuleIds.next(oldTempIndex);
11458 engAppRuleIds.delete(oldTempIndex);
11459 engRuleAppliedYN.delete(oldTempIndex);
11460 engAppItemClassIds.delete(oldTempIndex);
11461 engAppItemIds.delete(oldTempIndex);
11462 engAppPriorities.delete(oldTempIndex);
11463 engAppApproverCategories.delete(oldTempIndex);
11464 engAppRuleTypes.delete(oldTempIndex);
11465 engAppRuleItemClassIds.delete(oldTempIndex);
11466 engAppAppItemIds.delete(oldTempIndex);
11467 ruleDeleted := true;
11468 else
11469 tempIndex := engAppRuleIds.next(tempIndex);
11470 end if;
11471 exit when tempIndex is null;
11472 end loop;
11473 end if;
11474 end if;
11475 end loop;
11476 end if;
11477 /* If relative-priority processing deleted one or more rules from the engApp lists, compact them. */
11478 if(ruleDeleted) then
11479 compactEngAppLists(compactPrioritiesIn => true,
11480 compactActionTypeIdsIn => false,
11481 compactParametersIn => false);
11482 end if;
11483 exception
11484 when others then
11485 ame_util.runtimeException(packageNameIn => 'ame_engine',
11486 routineNameIn => 'processRelativePriorities',
11487 exceptionNumberIn => sqlcode,
11488 exceptionStringIn => sqlerrm);
11489 raise;
11490 end processRelativePriorities;
11491 procedure processUnresponsiveApprovers as
11492 engStApproversCount integer;
11493 tempIndex integer;
11494 tempSurrogateApprover ame_util.approverRecord2;
11495 begin
11496 /* First handle the empty-list case. */
11497 engStApproversCount := engStApprovers.count;
11498 if(engStApproversCount = 0) then
11499 return;
11500 end if;
11501 /* Now handle the non-empty case. */
11502 tempIndex := 1; /* post-increment */
11503 loop
11504 if(engStApprovers(tempIndex).approval_status = ame_util.noResponseStatus) then
11505 /* Fetch surrogate's wf_roles-specific data. */
11506 ame_approver_type_pkg.getSurrogate(origSystemIn => engStApprovers(tempIndex).orig_system,
11507 origSystemIdIn => engStApprovers(tempIndex).orig_system_id,
11508 origSystemIdOut => tempSurrogateApprover.orig_system_id,
11509 wfRolesNameOut => tempSurrogateApprover.name,
11510 displayNameOut => tempSurrogateApprover.display_name);
11511 tempSurrogateApprover.orig_system := engStApprovers(tempIndex).orig_system;
11512 /* Set fields constant for all surrogates. */
11513 tempSurrogateApprover.api_insertion := ame_util.apiInsertion;
11514 tempSurrogateApprover.source := ame_util.surrogateInsertion;
11515 /* Set common-valued fields. */
11516 tempSurrogateApprover.approver_category := engStApprovers(tempIndex).approver_category;
11517 tempSurrogateApprover.authority := engStApprovers(tempIndex).authority;
11518 tempSurrogateApprover.action_type_id := engStApprovers(tempIndex).action_type_id;
11519 tempSurrogateApprover.group_or_chain_id := engStApprovers(tempIndex).group_or_chain_id;
11520 tempSurrogateApprover.item_class := engStApprovers(tempIndex).item_class;
11521 tempSurrogateApprover.item_id := engStApprovers(tempIndex).item_id;
11522 tempSurrogateApprover.item_class_order_number := engStApprovers(tempIndex).item_class_order_number;
11523 tempSurrogateApprover.item_order_number := engStApprovers(tempIndex).item_order_number;
11524 tempSurrogateApprover.sub_list_order_number := engStApprovers(tempIndex).sub_list_order_number;
11525 tempSurrogateApprover.action_type_order_number := engStApprovers(tempIndex).action_type_order_number;
11526 tempSurrogateApprover.group_or_chain_order_number := engStApprovers(tempIndex).group_or_chain_order_number;
11527 /* Set remaining fields. */
11528 tempSurrogateApprover.occurrence :=
11529 getHandlerOccurrence(nameIn => tempSurrogateApprover.name,
11530 itemClassIn => tempSurrogateApprover.item_class,
11531 itemIdIn => tempSurrogateApprover.item_id,
11532 actionTypeIdIn => tempSurrogateApprover.action_type_id,
11533 groupOrChainIdIn => tempSurrogateApprover.group_or_chain_id);
11534 tempSurrogateApprover.approval_status := getHandlerApprovalStatus(approverIn => tempSurrogateApprover);
11535 /* The member order number and the approver order number are set here
11536 instead of in insertApprover. This will ensure that the surrogate has the same
11537 order as the unresponsive approver. Also changed call to insertApprover so that
11538 adjustMemberOrderNumbers is false */
11539 tempSurrogateApprover.member_order_number := engStApprovers(tempIndex).member_order_number;
11540 tempSurrogateApprover.approver_order_number := engStApprovers(tempIndex).approver_order_number;
11541 /* tempSurrogateApprover.approver_order_number also gets set later. */
11542 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
11543 fnd_log.string
11544 (fnd_log.level_statement
11545 ,'ame_engine.processUnresponsiveApprovers'
11546 ,'Unresponsive approver ::: ' || engStApprovers(tempIndex).name || ' Surrogate ::: ' || tempSurrogateApprover.name
11547 );
11548 end if;
11549 engTempReason := ame_approver_deviation_pkg.timeoutReason;
11550 engTempDate := sysdate;
11551 insertApprover(indexIn => tempIndex + 1,
11552 approverIn => tempSurrogateApprover,
11553 adjustMemberOrderNumbersIn => false);
11554 engStApproversCount := engStApproversCount + 1;
11555 end if;
11556 if(tempIndex = engStApproversCount) then
11557 exit;
11558 end if;
11559 tempIndex := tempIndex + 1;
11560 end loop;
11561 exception
11562 when others then
11563 ame_util.runtimeException(packageNameIn => 'ame_engine',
11564 routineNameIn => 'processUnresponsiveApprovers',
11565 exceptionNumberIn => sqlcode,
11566 exceptionStringIn => sqlerrm);
11567 raise;
11568 end processUnresponsiveApprovers;
11569 procedure repeatSubstitutions as
11570 currentActionTypeId integer;
11571 begin
11572 /* Check if any substitution rule exists. This can be done by checking if
11573 engAppSubHandlerFirstIndex is null or not */
11574 engRepSubFlag := 'Y';
11575 if not(engAppSubHandlerFirstIndex is null or
11576 engAppSubHandlerLastIndex is null) then
11577 /* Initialize the action-type state variables. */
11578 engAppHandlerFirstIndex := engAppSubHandlerFirstIndex;
11579 engAppHandlerLastIndex := engAppSubHandlerLastIndex;
11580 processActionType;
11581 end if;
11582 engRepSubFlag := 'N';
11583 end repeatSubstitutions;
11584 procedure setContext(isTestTransactionIn in boolean,
11585 isLocalTransactionIn in boolean,
11586 fetchConfigVarsIn in boolean,
11587 fetchOldApproversIn in boolean,
11588 fetchInsertionsIn in boolean,
11589 fetchDeletionsIn in boolean,
11590 fetchAttributeValuesIn in boolean,
11591 fetchInactiveAttValuesIn in boolean,
11592 processProductionActionsIn in boolean,
11593 processProductionRulesIn in boolean,
11594 updateCurrentApproverListIn in boolean,
11595 updateOldApproverListIn in boolean,
11596 processPrioritiesIn in boolean,
11597 prepareItemDataIn in boolean,
11598 prepareRuleIdsIn in boolean,
11599 prepareRuleDescsIn in boolean,
11600 prepareApproverTreeIn in boolean default false,
11601 transactionIdIn in varchar2,
11602 ameApplicationIdIn in integer default null,
11603 fndApplicationIdIn in integer default null,
11604 transactionTypeIdIn in varchar2 default null) as
11605 badLocalTransException exception;
11606 errorCode integer;
11607 errorMessage ame_util.longestStringType;
11608 nullValuesException exception;
11609 tempConfigVarValue ame_config_vars.variable_value%type;
11610 begin
11611 /*
11612 Clear all of the package variables, to be conservative. (The application server does not initialize
11613 package variables. See http://www-apps.us.oracle.com/atg/plans/r1153/plsqlglobals.txt for details.)
11614 */
11615 engLMParameterOnes.delete;
11616 engLMParameterTwos.delete;
11617 engGroupMemberGroupIds.delete;
11618 engGroupMemberNames.delete;
11619 engGroupMemberOrderNumbers.delete;
11620 engGroupMemberDisplayNames.delete;
11621 engGroupMemberOrigSystems.delete;
11622 engGroupMemberOrigSystemIds.delete;
11623 engGroupUseItemBind.delete;
11624 engAppActionTypeIds.delete;
11625 engAppApproverCategories.delete;
11626 engAppItemClassIds.delete;
11627 engAppItemIds.delete;
11628 engAppLMSubItemClassIds.delete;
11629 engAppLMSubItemIds.delete;
11630 engAppParameters.delete;
11631 engAppParameterTwos.delete;
11632 engAppPriorities.delete;
11633 engAppRuleIds.delete;
11634 engRuleAppliedYN.delete;
11635 engAppRuleTypes.delete;
11636 engAppRuleItemClassIds.delete;
11637 engAppAppItemIds.delete;
11638 engAppPerAppProdFirstIndexes.delete;
11639 engAppPerAppProdRuleIds.delete;
11640 engAppPerAppProdVariableNames.delete;
11641 engAppPerAppProdVariableValues.delete;
11642 engStApprovers.delete;
11643 /* Clear the engine approver tree */
11644 engStApproversTree.delete;
11645 engStItemClasses.delete;
11646 engStItemIds.delete;
11647 engStItemIndexes.delete;
11648 engStItemSources.delete;
11649 engStProductionIndexes.delete;
11650 /* Clear repeated indexes list */
11651 engStRepeatedIndexes.delete;
11652 engStRepeatedAppIndexes.delete;
11653 engStRuleDescriptions.delete;
11654 engStRuleIds.delete;
11655 engStRuleIndexes.delete;
11656 engStSourceTypes.delete;
11657 /* Clear suspended items list */
11658 engStSuspendedItems.delete;
11659 engStSuspendedItemClasses.delete;
11660 engStProductionsTable.delete;
11661 engStVariableNames.delete;
11662 engStVariableValues.delete;
11663 engStItemAppProcessCompleteYN.delete;
11664 engConfigVarNames.delete;
11665 engConfigVarValues.delete;
11666 engForwardingBehaviors.delete;
11667 engPriorityModes.delete;
11668 engPriorityThresholds.delete;
11669 engActionTypeChainOrderModes.delete;
11670 engActionTypeOrderNumbers.delete;
11671 engActionTypeVotingRegimes.delete;
11672 engActionTypeNames.delete;
11673 engActionTypeUsages.delete;
11674 engActionTypePackageNames.delete;
11675 engItemClassIds.delete;
11676 engItemClassIndexes.delete;
11677 engItemClassItemIdIndexes.delete;
11678 engItemClassNames.delete;
11679 engItemClassOrderNumbers.delete;
11680 engItemClassParModes.delete;
11681 engItemClassSublistModes.delete;
11682 engItemCounts.delete;
11683 engItemIds.delete;
11684 engAttributeIsStatics.delete;
11685 engAttributeItemClassIds.delete;
11686 engAttributeNames.delete;
11687 engAttributeTypes.delete;
11688 engAttributeValueIndexes.delete;
11689 engAttributeValues1.delete;
11690 engAttributeValues2.delete;
11691 engAttributeValues3.delete;
11692 engAttributeQueries.delete;
11693 engAttributeVariant.delete;
11694 engHeaderConditionValues.delete;
11695 engACUsageConditionIds.delete;
11696 engACUsageFirstIndexes.delete;
11697 engACUsageItemClassCounts.delete;
11698 engACUsageRuleIds.delete;
11699 engACUsageRulePriorities.delete;
11700 engACUsageRuleTypes.delete;
11701 engACUsageRuleApprCategories.delete;
11702 engACAttributeIds.delete;
11703 engACConditionTypes.delete;
11704 engACIncludeLowerLimits.delete;
11705 engACIncludeUpperLimits.delete;
11706 engACParameterOnes.delete;
11707 engACParameterThrees.delete;
11708 engACParameterTwos.delete;
11709 engACStringValueCounts.delete;
11710 engACStringValueFirstIndexes.delete;
11711 engACStringValues.delete;
11712 engOldApproverList.delete;
11713 engInsertedApproverList.delete;
11714 engInsertionOrderTypeList.delete;
11715 engInsertionParameterList.delete;
11716 engInsertionIsSpecialForwardee.delete;
11717 engDeletedApproverList.delete;
11718 engStInsertionIndexes.delete;
11719 /*delete deviation related info*/
11720 engDeviationResultList.delete;
11721 engInsertionReasonList.delete;
11722 engInsertionDateList.delete;
11723 engSuppressionDateList.delete;
11724 engSupperssionReasonList.delete;
11725 engInsApproverIndex.delete;
11726 engTempReason := null;
11727 engTempDate := null;
11728 engRepSubFlag := 'N';
11729 engSATOFlag := 'N';
11730 /* Fetch the transaction identifiers. */
11731 if(ameApplicationIdIn is null) then
11732 if(fndApplicationIdIn is null) then
11733 raise nullValuesException;
11734 end if;
11735 engFndApplicationId := fndApplicationIdIn;
11736 engTransactionTypeId := transactionTypeIdIn;
11737 engAmeApplicationId := fetchAmeApplicationId(fndApplicationIdIn => fndApplicationIdIn,
11738 transactionTypeIdIn => transactionTypeIdIn);
11739 else
11740 engAmeApplicationId := ameApplicationIdIn;
11741 fetchFndApplicationId(applicationIdIn => ameApplicationIdIn,
11742 fndApplicationIdOut => engFndApplicationId,
11743 transactionTypeIdOut => engTransactionTypeId);
11744 end if;
11745 engTransactionId := transactionIdIn;
11746 engIsTestTransaction := isTestTransactionIn;
11747 engIsLocalTransaction := isLocalTransactionIn;
11748 if(engIsTestTransaction and not engIsLocalTransaction) then
11749 raise badLocalTransException;
11750 end if;
11751 /* Initialize engEffectiveRuleDate to sysdate, in case the attribute values aren't fetched. */
11752 engEffectiveRuleDate := sysdate;
11753 /* Initialize misc. boolean globals to the corresponding input values. */
11754 engPrepareItemData := prepareItemDataIn;
11755 engPrepareRuleIds := prepareRuleIdsIn;
11756 engPrepareRuleDescs := prepareRuleDescsIn;
11757 engPrepareApproverTree := prepareApproverTreeIn;
11758 engItemDataPrepared := false;
11759 engProcessProductionActions := processProductionActionsIn;
11760 engProcessProductionRules := processProductionRulesIn;
11761 engProcessPriorities := processPrioritiesIn;
11762 engUpdateCurrentApproverList := updateCurrentApproverListIn;
11763 engUpdateOldApproverList := updateOldApproverListIn;
11764 /* Optionally fetch the global configuration-variable lists. */
11765 if(fetchConfigVarsIn) then
11766 /* Fetch. */
11767 fetchConfigVars;
11768 /* Reconcile the engProcessProduction values with the productionFunctionality config var. */
11769 tempConfigVarValue := getConfigVarValue(configVarNameIn => ame_util.productionConfigVar);
11770 if(engProcessProductionActions and
11771 tempConfigVarValue in (ame_util.noProductions, ame_util.perTransactionProductions)) then
11772 engProcessProductionActions := false;
11773 end if;
11774 if(engProcessProductionRules and
11775 tempConfigVarValue in (ame_util.noProductions, ame_util.perApproverProductions)) then
11776 engProcessProductionRules := false;
11777 end if;
11778 end if;
11779 /* Optionally fetch the transaction's attribute values. */
11780 if(fetchAttributeValuesIn) then
11781 /* Go fetch. */
11782 fetchItemClassData;
11783 fetchAttributeValues(fetchInactivesIn => fetchInactiveAttValuesIn);
11784 /* Set misc. frequently-used attribute-value caches. */
11785 engEvalPrioritiesPerItem :=
11786 getHeaderAttValue2(attributeNameIn => ame_util.evalPrioritiesPerItemAttribute) =
11787 ame_util.booleanAttributeTrue;
11788 engRepeatSubstitutions :=
11789 getHeaderAttValue2(attributeNameIn => ame_util.repeatSubstitutionsAttribute) =
11790 ame_util.booleanAttributeTrue;
11791 /* A null effective rule date should be interpreted as sysdate. */
11792 engEffectiveRuleDate := ame_util.versionStringToDate(stringDateIn =>
11793 getHeaderAttValue2(attributeNameIn => ame_util.effectiveRuleDateAttribute));
11794 if(engEffectiveRuleDate is null) then
11795 engEffectiveRuleDate := sysdate;
11796 else
11797 -- evaluate the attributes with use count 0 if they are used in rules
11798 -- which were active as of effective_rule_date.
11799 if not fetchInactiveAttValuesIn then
11800 fetchOtherAttributeValues;
11801 end if;
11802 end if;
11803 if(processProductionActionsIn or
11804 processProductionRulesIn or
11805 updateCurrentApproverListIn or
11806 updateOldApproverListIn or
11807 processPrioritiesIn or
11808 prepareItemDataIn or
11809 prepareRuleIdsIn or
11810 prepareRuleDescsIn) then
11811 /* Fetch the active condition usages. */
11812 fetchActiveConditionUsages;
11813 end if;
11814 end if;
11815 /* Optionally fetch the old approver list. */
11816 if(fetchOldApproversIn) then
11817 fetchOldApprovers;
11818 end if;
11819 /* Optionally fetch the inserted-approvers list. */
11820 if(fetchInsertionsIn) then
11821 fetchInsertedApprovers;
11822 end if;
11823 /* Optionally fetch the approver-deletions list. */
11824 if(fetchDeletionsIn) then
11825 fetchDeletedApprovers;
11826 end if;
11827 exception
11828 when badLocalTransException then
11829 errorCode := -20001;
11830 errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
11831 messageNameIn => 'AME_400688_ENG_TESTTX_NONLOCAL');
11832 ame_util.runtimeException(packageNameIn => 'ame_engine',
11833 routineNameIn => 'setContext',
11834 exceptionNumberIn => errorCode,
11835 exceptionStringIn => errorMessage);
11836 raise_application_error(errorCode,
11837 errorMessage);
11838 when nullValuesException then
11839 errorCode := -20001;
11840 errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
11841 messageNameIn => 'AME_400129_ENG_APPLID_NULL');
11842 ame_util.runtimeException(packageNameIn => 'ame_engine',
11843 routineNameIn => 'setContext',
11844 exceptionNumberIn => errorCode,
11845 exceptionStringIn => errorMessage);
11846 raise_application_error(errorCode,
11847 errorMessage);
11848 when others then
11849 ame_util.runtimeException(packageNameIn => 'ame_engine',
11850 routineNameIn => 'setContext',
11851 exceptionNumberIn => sqlcode,
11852 exceptionStringIn => sqlerrm);
11853 raise;
11854 end setContext;
11855 procedure setHandlerState(handlerNameIn in varchar2,
11856 parameterIn in varchar2 default null,
11857 stateIn in varchar2 default null) as
11858 argumentLengthException exception;
11859 errorCode integer;
11860 errorMessage ame_util.longestStringType;
11861 handlerName ame_temp_handler_states.handler_name%type;
11862 begin
11863 if(lengthb(stateIn) > 100 or
11864 lengthb(parameterIn) > 100) then
11865 raise argumentLengthException;
11866 end if;
11867 handlerName := upper(handlerNameIn);
11868 delete
11869 from ame_temp_handler_states
11870 where
11871 handler_name = handlerName and
11872 application_id = engAmeApplicationId and
11873 ((parameter is null and parameterIn is null) or
11874 (parameter = parameterIn));
11875 insert into ame_temp_handler_states(
11876 handler_name,
11877 row_timestamp,
11878 application_id,
11879 parameter,
11880 state)
11881 values(
11882 handlerName,
11883 sysdate, /* Don't use engEffectiveRuleDate here. */
11884 engAmeApplicationId,
11885 parameterIn,
11886 stateIn);
11887 exception
11888 when argumentLengthException then
11889 errorCode := -20001;
11890 errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
11891 messageNameIn => 'AME_400130_ENG_HDLR_PAR_LNG');
11892 ame_util.runtimeException(packageNameIn => 'ame_engine',
11893 routineNameIn => 'setHandlerState',
11894 exceptionNumberIn => errorCode,
11895 exceptionStringIn => errorMessage);
11896 raise_application_error(errorCode,
11897 errorMessage);
11898 when others then
11899 ame_util.runtimeException(packageNameIn => 'ame_engine',
11900 routineNameIn => 'setHandlerState',
11901 exceptionNumberIn => sqlcode,
11902 exceptionStringIn => sqlerrm);
11903 raise;
11904 end setHandlerState;
11905 procedure setInsertedApprovalStatus(currentApproverIndexIn in integer
11906 ,approvalStatusIn in varchar2) as
11907 insIndex Number;
11908 begin
11909 insIndex := engInsApproverIndex.first;
11910 if insIndex is not null then
11911 loop
11912 if engInsApproverIndex(insIndex) = currentApproverIndexIn then
11913 engInsertedApproverList(insIndex).approval_status := approvalStatusIn;
11914 update ame_temp_insertions
11915 set approval_status = approvalStatusIn
11916 where application_id = engAmeApplicationId
11917 and transaction_id = engTransactionId
11918 and insertion_order = engInsertionOrderList(insIndex)
11919 and order_type = engInsertionOrderTypeList(insIndex)
11920 and parameter = engInsertionParameterList(insIndex)
11921 and api_insertion = engInsertedApproverList(insIndex).api_insertion
11922 and authority = engInsertedApproverList(insIndex).authority;
11923 return;
11924 end if;
11925 exit when insIndex = engInsApproverIndex.last;
11926 insIndex := engInsApproverIndex.next(insIndex);
11927 end loop;
11928 end if;
11929 exception
11930 when others then
11931 ame_util.runtimeException(packageNameIn => 'ame_engine',
11932 routineNameIn => 'setInsertedApprovalStatus',
11933 exceptionNumberIn => sqlcode,
11934 exceptionStringIn => sqlerrm);
11935 raise;
11936 end setInsertedApprovalStatus;
11937 procedure setRuleApplied(ruleIndexIn in integer) as
11938 begin
11939 engRuleAppliedYN(ruleIndexIn) := ame_util.booleanTrue;
11940 end setRuleApplied;
11941 procedure sortApplicableRules(sortByActionTypeIn in boolean) as
11942 exchangeActionTypeId integer;
11943 exchangeAppItemId ame_util.stringType;
11944 exchangeApproverCategory ame_util.charType;
11945 exchangeItemClassId integer;
11946 exchangeItemId ame_util.stringType;
11947 exchangeParameter ame_actions.parameter%type;
11948 exchangeParameterTwo ame_actions.parameter_two%type;
11949 exchangePriority integer;
11950 exchangeRuleId integer;
11951 exchangeRuleItemClassId integer;
11952 exchangeRuleType ame_util.stringType;
11953 exchangeRuleAppliedYN ame_util.charType;
11954 begin
11955 /*
11956 This is a simple sort algorithm, but it is efficient for small input counts.
11957 The inputs are generally nearly sorted, which makes at least a nonrandomized
11958 quicksort a poor choice (quicksort's worst-case performance arises in the
11959 case of inputs that are already sorted or nearly sorted). A randomized
11960 quicksort would avoid this problem, but our judgment is that the random-number
11961 generation overhead makes this approach undesirable for inputs of the sizes
11962 we expect.
11963 */
11964 for i in 2 .. engAppRuleIds.count loop
11965 for j in 1 .. i - 1 loop
11966 if(compareApplicableRules(index1In => i,
11967 index2In => j,
11968 compareActionTypesIn => sortbyActionTypeIn)) then
11969 /* Set exchange buffers' values. */
11970 exchangeItemClassId := engAppItemClassIds(i);
11971 exchangeItemId := engAppItemIds(i);
11972 exchangeRuleItemClassId := engAppRuleItemClassIds(i);
11973 exchangeAppItemId := engAppAppItemIds(i);
11974 exchangeRuleId := engAppRuleIds(i);
11975 exchangeRuleAppliedYN := engRuleAppliedYN(i);
11976 exchangeRuleType := engAppRuleTypes(i);
11977 exchangeApproverCategory := engAppApproverCategories(i);
11978 if(sortByActionTypeIn) then
11979 exchangeActionTypeId := engAppActionTypeIds(i);
11980 exchangeParameter := engAppParameters(i);
11981 exchangeParameterTwo := engAppParameterTwos(i);
11982 elsif(engProcessPriorities) then
11983 exchangePriority := engAppPriorities(i);
11984 end if;
11985 /* Move jth values to index i. */
11986 engAppRuleItemClassIds(i) := engAppRuleItemClassIds(j);
11987 engAppAppItemIds(i) := engAppAppItemIds(j);
11988 engAppItemClassIds(i) := engAppItemClassIds(j);
11989 engAppItemIds(i) := engAppItemIds(j);
11990 engAppRuleIds(i) := engAppRuleIds(j);
11991 engRuleAppliedYN(i) := engRuleAppliedYN(j);
11992 engAppRuleTypes(i) := engAppRuleTypes(j);
11993 engAppApproverCategories(i) := engAppApproverCategories(j);
11994 if(sortByActionTypeIn) then
11995 engAppActionTypeIds(i) := engAppActionTypeIds(j);
11996 engAppParameters(i) := engAppParameters(j);
11997 engAppParameterTwos(i) := engAppParameterTwos(j);
11998 elsif(engProcessPriorities) then
11999 engAppPriorities(i) := engAppPriorities(j);
12000 end if;
12001 /* Move buffered ith values to index j. */
12002 engAppRuleItemClassIds(j) := exchangeRuleItemClassId;
12003 engAppAppItemIds(j) := exchangeAppItemId;
12004 engAppItemClassIds(j) := exchangeItemClassId;
12005 engAppItemIds(j) := exchangeItemId;
12006 engAppRuleIds(j) := exchangeRuleId;
12007 engRuleAppliedYN(j) := exchangeRuleAppliedYN;
12008 engAppRuleTypes(j) := exchangeRuleType;
12009 engAppApproverCategories(j) := exchangeApproverCategory;
12010 if(sortByActionTypeIn) then
12011 engAppActionTypeIds(j) := exchangeActionTypeId;
12012 engAppParameters(j) := exchangeParameter;
12013 engAppParameterTwos(j) := exchangeParameterTwo;
12014 elsif(engProcessPriorities) then
12015 engAppPriorities(j) := exchangePriority;
12016 end if;
12017 end if;
12018 end loop;
12019 end loop;
12020 exception
12021 when others then
12022 ame_util.runtimeException(packageNameIn => 'ame_engine',
12023 routineNameIn => 'sortApplicableRules',
12024 exceptionNumberIn => sqlcode,
12025 exceptionStringIn => sqlerrm);
12026 raise;
12027 end sortApplicableRules;
12028 procedure substituteApprover(approverIndexIn in integer,
12029 nameIn in varchar2,
12030 actionTypeIdIn in varchar2,
12031 ruleIdIn in integer) as
12032 currentActionTypeId integer;
12033 currentGroupOrChainId integer;
12034 occurrence integer;
12035 l_error_code number;
12036 errorCode integer;
12037 errorMessage ame_util.longestStringType;
12038 begin
12039 /* Look up the orig_system, orig_system_id, and display_name values corresponding to nameIn. */
12040 begin
12041 ame_approver_type_pkg.getOrigSystemIdAndDisplayName(
12042 nameIn => nameIn,
12043 origSystemOut => engStApprovers(approverIndexIn).orig_system,
12044 origSystemIdOut => engStApprovers(approverIndexIn).orig_system_id,
12045 displayNameOut => engStApprovers(approverIndexIn).display_name);
12046 exception
12047 when others then
12048 l_error_code := sqlcode;
12049 if l_error_code = -20213 then
12050 errorCode := -20220;
12051 errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
12052 messageNameIn => 'AME_400837_INV_APR_FOUND',
12053 tokenNameOneIn => 'PROCESS_NAME',
12054 tokenValueOneIn => 'ame_engine.substituteApprover',
12055 tokenNameTwoIn => 'NAME',
12056 tokenValueTwoIn => nameIn);
12057 raise_application_error(errorCode,errorMessage);
12058 end if;
12059 raise;
12060 end;
12061
12062 /* Calculate the occurrence value for the substitution. */
12063 currentGroupOrChainId := engStApprovers(approverIndexIn).group_or_chain_id;
12064 occurrence := 1;
12065 for i in reverse 1 .. (approverIndexIn - 1) loop
12066 if(currentGroupOrChainId <> engStApprovers(i).group_or_chain_id or
12067 engStApprovers(approverIndexIn).action_type_id <> engStApprovers(i).action_type_id or
12068 engStApprovers(approverIndexIn).item_id <> engStApprovers(i).item_id or
12069 engStApprovers(approverIndexIn).item_class <> engStApprovers(i).item_class) then
12070 exit;
12071 end if;
12072 if(nameIn = engStApprovers(i).name) then
12073 occurrence := occurrence + 1;
12074 end if;
12075 end loop;
12076 engStApprovers(approverIndexIn).name := nameIn;
12077 engStApprovers(approverIndexIn).occurrence := occurrence;
12078 /* Get and set the approval status. */
12079 engStApprovers(approverIndexIn).approval_status :=
12080 getHandlerApprovalStatus(approverIn => engStApprovers(approverIndexIn));
12081 if(engStApprovers(approverIndexIn).approval_status = ame_util.noResponseStatus
12082 and engRepSubFlag = 'Y' ) then
12083 engSATOFlag := 'Y';
12084 end if;
12085 /* Append ruleIdIn to source value. */
12086 ame_util.appendRuleIdToSource(ruleIdIn => ruleIdIn,
12087 sourceInOut => engStApprovers(approverIndexIn).source);
12088 /* Update the occurrence values of the same approver wherever the approver occurs later in the same chain. */
12089 for i in approverIndexIn + 1 .. engStApprovers.count loop
12090 if(currentGroupOrChainId <> engStApprovers(i).group_or_chain_id or
12091 engStApprovers(approverIndexIn).action_type_id <> engStApprovers(i).action_type_id or
12092 engStApprovers(approverIndexIn).item_id <> engStApprovers(i).item_id or
12093 engStApprovers(approverIndexIn).item_class <> engStApprovers(i).item_class) then
12094 exit;
12095 end if;
12096 if(nameIn = engStApprovers(i).name) then
12097 occurrence := occurrence + 1;
12098 engStApprovers(i).occurrence := occurrence;
12099 /* Get and set the approval status for this approver's approval status. */
12100 engStApprovers(i).approval_status :=
12101 getHandlerApprovalStatus(approverIn => engStApprovers(i));
12102 end if;
12103 end loop;
12104 exception
12105 when others then
12106 ame_util.runtimeException(packageNameIn => 'ame_engine',
12107 routineNameIn => 'substituteApprover',
12108 exceptionNumberIn => sqlcode,
12109 exceptionStringIn => sqlerrm);
12110 raise;
12111 end substituteApprover;
12112 procedure truncateChain(approverIndexIn in integer,
12113 ruleIdIn in integer) as
12114 currentActionTypeId integer;
12115 currentGroupOrChainId integer;
12116 engStApproversCount integer;
12117 firstIndexToTruncate integer;
12118 lastIndexToTruncate integer;
12119 siblingTreeNodeIndex integer;
12120 tempIndex integer;
12121 truncateCount integer;
12122 loopIndex integer;
12123 nextIndex integer;
12124 begin
12125 /*
12126 This procedure copies the current action-type ID and group-or-chain ID into local
12127 variables for efficiency, but does not copy the item ID or item class because these
12128 copy operations are likely to take much longer, and to require substantially more
12129 memory-allocation overhead.
12130 */
12131 currentActionTypeId := engStApprovers(approverIndexIn).action_type_id;
12132 currentGroupOrChainId := engStApprovers(approverIndexIn).group_or_chain_id;
12133 engStApproversCount := engStApprovers.count;
12134 /* First handle the case where no truncation is required. */
12135 tempIndex := approverIndexIn + 1;
12136 if(approverIndexIn = engStApproversCount or
12137 currentGroupOrChainId <> engStApprovers(tempIndex).group_or_chain_id or
12138 currentActionTypeId <> engStApprovers(tempIndex).action_type_id or
12139 engStApprovers(approverIndexIn).item_id <> engStApprovers(tempIndex).item_id or
12140 engStApprovers(approverIndexIn).item_class <> engStApprovers(tempIndex).item_class) then
12141 return;
12142 end if;
12143 /* Evidently the approver at tempIndex is in the same chain. Find the last approver in that chain. */
12144 firstIndexToTruncate := tempIndex;
12145 lastIndexToTruncate := firstIndexToTruncate;
12146 for i in firstIndexToTruncate + 1 .. engStApproversCount loop
12147 /* Stop at the end of the chain. */
12148 if(currentGroupOrChainId <> engStApprovers(i).group_or_chain_id or
12149 currentActionTypeId <> engStApprovers(i).action_type_id or
12150 engStApprovers(approverIndexIn).item_id <> engStApprovers(i).item_id or
12151 engStApprovers(approverIndexIn).item_class <> engStApprovers(i).item_class) then
12152 lastIndexToTruncate := i - 1;
12153 exit;
12154 end if;
12155 if(i = engStApproversCount) then
12156 lastIndexToTruncate := engStApproversCount;
12157 end if;
12158 end loop;
12159 /*
12160 Truncate from the first index to the last index, inclusive.
12161 delete the rest of the chain.
12162 */
12163 truncateCount := lastIndexToTruncate - firstIndexToTruncate + 1;
12164 /* Copy the end of the list down truncateCount places. */
12165 for i in firstIndexToTruncate .. (engStApproversCount - truncateCount) loop
12166 ame_util.copyApproverRecord2(approverRecord2In => engStApprovers(i + truncateCount),
12167 approverRecord2Out => engStApprovers(i));
12168 end loop;
12169 /* Code to delete the approvers from the tree whenever there are approver suppressions */
12170 if engPrepareApproverTree then
12171 siblingTreeNodeIndex := ame_util.noSiblingIndex;
12172 /* Approvers Tree is sparse */
12173 loopIndex := engStApproversTree.last;
12174 loop
12175 if engStApproversTree(loopIndex).tree_level = 6 then
12176 if engStApproversTree(loopIndex).approver_index >= firstIndexToTruncate + truncateCount then
12177 engStApproversTree(loopIndex).approver_index := engStApproversTree(loopIndex).approver_index - truncateCount;
12178 nextIndex := engStApproversTree.prior(loopIndex);
12179 elsif engStApproversTree(loopIndex).approver_index >= firstIndexToTruncate
12180 and engStApproversTree(loopIndex).approver_index < lastIndexToTruncate then
12181 nextIndex := engStApproversTree.prior(loopIndex);
12182 engStApproversTree.delete(loopIndex);
12183 elsif engStApproversTree(loopIndex).approver_index = lastIndexToTruncate then
12184 siblingTreeNodeIndex := engStApproversTree(loopIndex).sibling_index;
12185 nextIndex := engStApproversTree.prior(loopIndex);
12186 engStApproversTree.delete(loopIndex);
12187 elsif engStApproversTree(loopIndex).approver_index = firstIndexToTruncate - 1 then
12188 engStApproversTree(loopIndex).sibling_index := siblingTreeNodeIndex;
12189 nextIndex := engStApproversTree.prior(loopIndex);
12190 else
12191 nextIndex := engStApproversTree.prior(loopIndex);
12192 end if;
12193 else
12194 nextIndex := engStApproversTree.prior(loopIndex);
12195 end if;
12196 exit when engStApproversTree.first = nextIndex;
12197 loopIndex := nextIndex;
12198 end loop;
12199 end if;
12200 /* Delete the last truncateCount places. */
12201 engStApprovers.delete(engStApproversCount - truncateCount + 1, engStApproversCount);
12202 exception
12203 when others then
12204 ame_util.runtimeException(packageNameIn => 'ame_engine',
12205 routineNameIn => 'truncateChain',
12206 exceptionNumberIn => sqlcode,
12207 exceptionStringIn => sqlerrm);
12208 raise;
12209 end truncateChain;
12210 procedure unlockTransaction(fndApplicationIdIn in integer,
12211 transactionIdIn in varchar2,
12212 transactionTypeIdIn in varchar2 default null) as
12213 begin
12214 if(engTransactionIsLocked) then
12215 delete from ame_temp_trans_locks
12216 where
12217 fnd_application_id = fndApplicationIdIn and
12218 ((transaction_type_id is null and transactionTypeIdIn is null) or
12219 transaction_type_id = transactionTypeIdIn) and
12220 transaction_id = transactionIdIn;
12221 end if;
12222 engTransactionIsLocked := false;
12223 exception
12224 when others then
12225 ame_util.runtimeException(packageNameIn => 'ame_engine',
12226 routineNameIn => 'unlockTransaction',
12227 exceptionNumberIn => sqlcode,
12228 exceptionStringIn => sqlerrm);
12229 raise;
12230 end unlockTransaction;
12231 procedure updateTransactionState(isTestTransactionIn in boolean,
12232 isLocalTransactionIn in boolean,
12233 fetchConfigVarsIn in boolean,
12234 fetchOldApproversIn in boolean,
12235 fetchInsertionsIn in boolean,
12236 fetchDeletionsIn in boolean,
12237 fetchAttributeValuesIn in boolean,
12238 fetchInactiveAttValuesIn in boolean,
12239 processProductionActionsIn in boolean,
12240 processProductionRulesIn in boolean,
12241 updateCurrentApproverListIn in boolean,
12242 updateOldApproverListIn in boolean,
12243 processPrioritiesIn in boolean,
12244 prepareItemDataIn in boolean,
12245 prepareRuleIdsIn in boolean,
12246 prepareRuleDescsIn in boolean,
12247 prepareApproverTreeIn in boolean default false,
12248 transactionIdIn in varchar2,
12249 ameApplicationIdIn in integer default null,
12250 fndApplicationIdIn in integer default null,
12251 transactionTypeIdIn in varchar2 default null) as
12252 configVarException exception;
12253 errorCode integer;
12254 errorMessage ame_util.longestStringType;
12255 begin
12256 setContext(isTestTransactionIn => isTestTransactionIn,
12257 isLocalTransactionIn => isLocalTransactionIn,
12258 fetchConfigVarsIn => fetchConfigVarsIn,
12259 fetchOldApproversIn => fetchOldApproversIn,
12260 fetchInsertionsIn => fetchInsertionsIn,
12261 fetchDeletionsIn => fetchDeletionsIn,
12262 fetchAttributeValuesIn => fetchAttributeValuesIn,
12263 fetchInactiveAttValuesIn => fetchInactiveAttValuesIn,
12264 processProductionActionsIn => processProductionActionsIn,
12265 processProductionRulesIn => processProductionRulesIn,
12266 updateCurrentApproverListIn => updateCurrentApproverListIn,
12267 updateOldApproverListIn => updateOldApproverListIn,
12268 processPrioritiesIn => processPrioritiesIn,
12269 prepareItemDataIn => prepareItemDataIn,
12270 prepareRuleIdsIn => prepareRuleIdsIn,
12271 prepareRuleDescsIn => prepareRuleDescsIn,
12272 prepareApproverTreeIn => prepareApproverTreeIn,
12273 transactionIdIn => transactionIdIn,
12274 ameApplicationIdIn => ameApplicationIdIn,
12275 fndApplicationIdIn => fndApplicationIdIn,
12276 transactionTypeIdIn => transactionTypeIdIn);
12277 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
12278 fnd_log.string
12279 (fnd_log.level_statement
12280 ,'ame_engine.updateTransactionState'
12281 ,'AME Application Id ::: ' || engAmeApplicationId
12282 );
12283 fnd_log.string
12284 (fnd_log.level_statement
12285 ,'ame_engine.updateTransactionState'
12286 ,'AME Transaction Id ::: ' || engTransactionId
12287 );
12288 end if;
12289 /* Added from version 115.217 to log a transaction (backward compatiblity)*/
12290 if updateOldApproverListIn then
12291 logTransaction;
12292 end if;
12293 if(processProductionActionsIn or
12294 processProductionRulesIn or
12295 updateCurrentApproverListIn or
12296 updateOldApproverListIn or
12297 processPrioritiesIn or
12298 prepareItemDataIn or
12299 prepareRuleIdsIn or
12300 prepareRuleDescsIn) then
12301 if(not fetchConfigVarsIn) then
12302 raise configVarException;
12303 end if;
12304 evaluateRules;
12305 fetchApplicableActions;
12306 processExceptions;
12307 end if;
12308 if(updateCurrentApproverListIn or
12309 updateOldApproverListIn) then
12310 processRules(processOnlyProductionsIn => false);
12311 elsif(processProductionRulesIn) then
12312 processRules(processOnlyProductionsIn => true);
12313 end if;
12314 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
12315 fnd_log.string
12316 (fnd_log.level_statement
12317 ,'ame_engine.updateTransactionState'
12318 ,'Approver count after processRules ::: ' || engStApprovers.count
12319 );
12320 end if;
12321 if(updateCurrentApproverListIn or
12322 updateOldApproverListIn) then
12323 processAdHocInsertions;
12324 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
12325 fnd_log.string
12326 (fnd_log.level_statement
12327 ,'ame_engine.updateTransactionState'
12328 ,'Approver count after processAdHocInsertions ::: ' || engStApprovers.count
12329 );
12330 end if;
12331 processUnresponsiveApprovers;
12332 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
12333 fnd_log.string
12334 (fnd_log.level_statement
12335 ,'ame_engine.updateTransactionState'
12336 ,'Approver count after processUnresponsiveApprovers ::: ' || engStApprovers.count
12337 );
12338 end if;
12339 if engRepeatSubstitutions then
12340 repeatSubstitutions;
12341 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
12342 fnd_log.string
12343 (fnd_log.level_statement
12344 ,'ame_engine.updateTransactionState'
12345 ,'Approver count after repeatSubstitutions ::: ' || engStApprovers.count
12346 );
12347 end if;
12348 end if;
12349
12350 /*
12351 processSuppressions must precede processRepeatedApprovers, because the latter procedure needs to see
12352 any approver deletions, to aggregate approvers correctly.
12353 */
12354 processSuppressions;
12355 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
12356 fnd_log.string
12357 (fnd_log.level_statement
12358 ,'ame_engine.updateTransactionState'
12359 ,'Approver count after processSuppressions ::: ' || engStApprovers.count
12360 );
12361 end if;
12362 /*
12363 processSuppressions must precede processRepeatedApprovers so every approver in engStApprovers still
12364 has non-null item_class and item_id fields.
12365 */
12366 processRepeatedApprovers;
12367 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
12368 fnd_log.string
12369 (fnd_log.level_statement
12370 ,'ame_engine.updateTransactionState'
12371 ,'Approver count after processRepeatedApprovers ::: ' || engStApprovers.count
12372 );
12373 end if;
12374 /*
12375 processRepeatedApprovers must precede populateEngStVariables so the latter can treat repeated
12376 approvers as equivalent to approving approvers, for purposes of determining whether an item or
12377 transaction's approval process is complete.
12378 */
12379 populateEngStVariables;
12380 if engPrepareApproverTree then
12381 calculateApproverOrderNumbers;
12382 if updateOldApproverListIn then
12383 ame_approver_deviation_pkg.updateDeviationState(
12384 engAmeApplicationId
12385 ,engTransactionId
12386 ,engDeviationResultList
12387 ,engStApprovalProcessCompleteYN
12388 ,engStApprovers);
12389 end if;
12390 end if;
12391 if fnd_log.g_current_runtime_level <= fnd_log.level_statement then
12392 if engStApprovers.count = 0 then
12393 fnd_log.string
12394 (fnd_log.level_statement
12395 ,'ame_engine.updateTransactionState'
12396 ,'**************** No Approvers ******************'
12397 );
12398 else
12399 for i in 1 .. engStApprovers.count loop
12400 fnd_log.string
12401 (fnd_log.level_statement
12402 ,'ame_engine.updateTransactionState'
12403 ,'Approver ::: ' || engStApprovers(i).name || ' Order Number ::: ' || engStApprovers(i).approver_order_number
12404 );
12405 end loop;
12406 end if;
12407 end if;
12408 if(updateOldApproverListIn) then
12409 updateOldApproverList;
12410 end if;
12411 end if;
12412 exception
12413 when configVarException then
12414 errorCode := -20001;
12415 errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
12416 messageNameIn => 'AME_400691_INV_PARAM_ENG_UPDTX');
12417 ame_util.runtimeException(packageNameIn => 'ame_engine',
12418 routineNameIn => 'updateTransactionState',
12419 exceptionNumberIn => errorCode,
12420 exceptionStringIn => errorMessage);
12421 raise_application_error(errorCode,
12422 errorMessage);
12423 when others then
12424 ame_util.runtimeException(packageNameIn => 'ame_engine',
12425 routineNameIn => 'updateTransactionState',
12426 exceptionNumberIn => sqlcode,
12427 exceptionStringIn => sqlerrm);
12428 raise;
12429 end updateTransactionState;
12430 procedure updateOldApproverList as
12431 tempActionTypeIds ame_util.idList;
12432 tempApiValues ame_util.charList;
12433 tempAuthorityValues ame_util.charList;
12434 tempCategories ame_util.charList;
12435 tempCount integer;
12436 tempGroupOrChainIds ame_util.idList;
12437 tempItemClasses ame_util.stringList;
12438 tempItemIds ame_util.stringList;
12439 tempNames ame_util.longStringList;
12440 tempOccurrences ame_util.idList;
12441 tempOrderNumbers ame_util.idList;
12442 tempStatuses ame_util.stringList;
12443 begin
12444 delete from ame_temp_old_approver_lists
12445 where
12446 application_id = engAmeApplicationId and
12447 transaction_id = engTransactionId;
12448 /*
12449 Bulk insert the transaction's current state into ame_temp_old_approver_lists.
12450 Take the state from engStApprovers, to account for all operations on the approver list.
12451 */
12452 ame_util.convertApproversTable2ToValues(approversTableIn => engStApprovers,
12453 namesOut => tempNames,
12454 itemClassesOut => tempItemClasses,
12455 itemIdsOut => tempItemIds,
12456 apiInsertionsOut => tempApiValues,
12457 authoritiesOut => tempAuthorityValues,
12458 actionTypeIdsOut => tempActionTypeIds,
12459 groupOrChainIdsOut => tempGroupOrChainIds,
12460 occurrencesOut => tempOccurrences,
12461 approverCategoriesOut => tempCategories,
12462 statusesOut => tempStatuses);
12463 tempCount := tempNames.count;
12464 for i in 1 .. tempCount loop
12465 if engStApprovers.exists(i) and engStApprovers(i).approver_order_number is not null then
12466 tempOrderNumbers(i) := engStApprovers(i).approver_order_number;
12467 else
12468 tempOrderNumbers(i) := i;
12469 end if;
12470 end loop;
12471 for i in 1..engStApprovers.count loop
12472 setInsertedApprovalStatus(currentApproverIndexIn => i
12473 ,approvalStatusIn => engStApprovers(i).approval_status);
12474 end loop;
12475 forall i in 1 .. tempCount
12476 insert into ame_temp_old_approver_lists(
12477 transaction_id,
12478 application_id,
12479 order_number,
12480 name,
12481 item_class,
12482 item_id,
12483 api_insertion,
12484 authority,
12485 action_type_id,
12486 group_or_chain_id,
12487 occurrence,
12488 approver_category,
12489 approval_status) values(
12490 engTransactionId,
12491 engAmeApplicationId,
12492 tempOrderNumbers(i),
12493 tempNames(i),
12494 tempItemClasses(i),
12495 tempItemIds(i),
12496 tempApiValues(i),
12497 tempAuthorityValues(i),
12498 tempActionTypeIds(i),
12499 tempGroupOrChainIds(i),
12500 tempOccurrences(i),
12501 tempCategories(i),
12502 tempStatuses(i));
12503 exception
12504 when others then
12505 ame_util.runtimeException(packageNameIn => 'ame_engine',
12506 routineNameIn => 'updateOldApproverList',
12507 exceptionNumberIn => sqlcode,
12508 exceptionStringIn => sqlerrm);
12509 raise;
12510 end updateOldApproverList;
12511 /* test procedure */
12512 procedure testEngine(printContextYNIn in varchar2 default 'N',
12513 printAppRulesYNIn in varchar2 default 'N',
12514 printApproversYNIn in varchar2 default 'N') as
12515 begin
12516 null;
12517 exception
12518 when others then
12519 ame_util.runtimeException(packageNameIn => 'ame_engine',
12520 routineNameIn => 'testEngine',
12521 exceptionNumberIn => sqlcode,
12522 exceptionStringIn => sqlerrm);
12523 raise;
12524 end testEngine;
12525 procedure updateApprovalStatus(applicationIdIn in number,
12526 transactionTypeIn in varchar2,
12527 transactionIdIn in varchar2,
12528 approverIn in ame_util.approverRecord2,
12529 notificationIn in ame_util2.notificationRecord
12530 default ame_util2.emptyNotificationRecord,
12531 forwardeeIn in ame_util.approverRecord2 default
12532 ame_util.emptyApproverRecord2,
12533 updateItemIn in boolean default false) as
12534 ameApplicationId integer;
12535 apiInsertionException exception;
12536 approver ame_util.approverRecord2;
12537 approverInIndex integer;
12538 approverInIsSpecialForwardee boolean;
12539 badApproverException exception;
12540 badForwardeeException exception;
12541 badStatusException exception;
12542 currentApprovers ame_util.approversTable2;
12543 errorCode integer;
12544 errorMessage ame_util.longStringType;
12545 l_error_code number;
12546 firstIndexInChain integer;
12547 forwardee ame_util.approverRecord2;
12548 forwardeeIndex integer;
12549 forwardeeType ame_util.stringType;
12550 forwarderFound boolean;
12551 forwarderType ame_util.stringType;
12552 forwardingBehavior ame_util.stringType;
12553 insertedApprover ame_util.approverRecord2;
12554 prevApproverIndex integer;
12555 prevApproverOccurrence integer;
12556 repeatedIndexes ame_util.idList;
12557 repeatedAppIndexes ame_util.idList;
12558 superiorApprover ame_util.approverRecord2;
12559 tempInsertionOrder integer;
12560 tempParameter ame_temp_insertions.parameter%type;
12561 tempCOAGroupActionTypeId integer;
12562 tempPreGroupActionTypeId integer;
12563 tempPostGroupActionTypeId integer;
12564 votingRegime ame_util.charType;
12565 approverOldApprovalStatus varchar2(50);
12566 tempReason varchar2(50);
12567 tempStatus varchar2(50);
12568 tempfrwCount number;
12569 l_actiontypeName varchar2(50);
12570 l_votingRegime varchar2(20);
12571 l_actionTypeId Number;
12572 l_frw_index number;
12573 begin
12574 /* Lock the transaction. */
12575 ame_engine.lockTransaction(fndApplicationIdIn => applicationIdIn,
12576 transactionIdIn => transactionIdIn,
12577 transactionTypeIdIn => transactionTypeIn);
12578 /* Clear the exception log when required. */
12579 if(approverIn.approval_status = ame_util.clearExceptionsStatus) then
12580 delete from ame_exceptions_log
12581 where
12582 transaction_id = transactionIdIn and
12583 application_id = ameApplicationId;
12584 ame_engine.unlockTransaction(fndApplicationIdIn => applicationIdIn,
12585 transactionIdIn => transactionIdIn,
12586 transactionTypeIdIn => transactionTypeIn);
12587 return;
12588 end if;
12589 /* Locate approverIn in the current approver list, if possible. */
12590 ame_engine.updateTransactionState(isTestTransactionIn => false,
12591 isLocalTransactionIn => false,
12592 fetchConfigVarsIn => true,
12593 fetchOldApproversIn => true,
12594 fetchInsertionsIn => true,
12595 fetchDeletionsIn => true,
12596 fetchAttributeValuesIn => true,
12597 fetchInactiveAttValuesIn => false,
12598 processProductionActionsIn => false,
12599 processProductionRulesIn => false,
12600 updateCurrentApproverListIn => true,
12601 updateOldApproverListIn => false,
12602 processPrioritiesIn => true,
12603 prepareItemDataIn => false,
12604 prepareRuleIdsIn => false,
12605 prepareRuleDescsIn => false,
12606 prepareApproverTreeIn => true,
12607 transactionIdIn => transactionIdIn,
12608 ameApplicationIdIn => null,
12609 fndApplicationIdIn => applicationIdIn,
12610 transactionTypeIdIn => transactionTypeIn);
12611 ame_engine.getApprovers(approversOut => currentApprovers);
12612 ame_engine.getRepeatedIndexes(repeatedIndexesOut => repeatedIndexes
12613 ,repeatedAppIndexesOut => repeatedAppIndexes);
12614 ameApplicationId := ame_engine.getAmeApplicationId;
12615 approverInIndex := null;
12616 if(approverIn.occurrence is null or
12617 approverIn.group_or_chain_id is null or
12618 approverIn.action_type_id is null or
12619 approverIn.item_id is null or
12620 approverIn.item_class is null) then /* partial match */
12621 /* We need to split the search below to take in to account that the user
12622 could be trying to clear an approvers status */
12623 if(approverIn.approval_status is null) then /* Clear Approver status */
12624 for i in 1 .. currentApprovers.count loop
12625 if(approverIn.name = currentApprovers(i).name and
12626 (currentApprovers(i).approval_status = ame_util.approvedStatus or
12627 currentApprovers(i).approval_status = ame_util.approveAndForwardStatus or
12628 currentApprovers(i).approval_status = ame_util.forwardStatus or
12629 currentApprovers(i).approval_status = ame_util2.reassignStatus or
12630 currentApprovers(i).approval_status = ame_util.rejectStatus or
12631 currentApprovers(i).approval_status = ame_util.notifiedStatus or
12632 currentApprovers(i).approval_status = ame_util.exceptionStatus or
12633 currentApprovers(i).approval_status = ame_util.noResponseStatus ) and
12634 (approverIn.occurrence is null or
12635 approverIn.occurrence = currentApprovers(i).occurrence) and
12636 (approverIn.group_or_chain_id is null or
12637 approverIn.group_or_chain_id = currentApprovers(i).group_or_chain_id) and
12638 (approverIn.action_type_id is null or
12639 approverIn.action_type_id = currentApprovers(i).action_type_id) and
12640 (approverIn.item_id is null or
12641 approverIn.item_id = currentApprovers(i).item_id) and
12642 (approverIn.item_class is null or
12643 approverIn.item_class = currentApprovers(i).item_class)) then
12644 approverInIndex := i;
12645 exit;
12646 end if;
12647 end loop;
12648 else
12649 for i in 1 .. currentApprovers.count loop
12650 if(approverIn.name = currentApprovers(i).name and
12651 (currentApprovers(i).approval_status is null or
12652 currentApprovers(i).approval_status = ame_util.nullStatus or
12653 (currentApprovers(i).approver_category = ame_util.approvalApproverCategory and
12654 currentApprovers(i).approval_status = ame_util.notifiedStatus)) and
12655 (approverIn.occurrence is null or
12656 approverIn.occurrence = currentApprovers(i).occurrence) and
12657 (approverIn.group_or_chain_id is null or
12658 approverIn.group_or_chain_id = currentApprovers(i).group_or_chain_id) and
12659 (approverIn.action_type_id is null or
12660 approverIn.action_type_id = currentApprovers(i).action_type_id) and
12661 (approverIn.item_id is null or
12662 approverIn.item_id = currentApprovers(i).item_id) and
12663 (approverIn.item_class is null or
12664 approverIn.item_class = currentApprovers(i).item_class)) then
12665 approverInIndex := i;
12666 exit;
12667 end if;
12668 end loop;
12669 end if;
12670 else /* complete match */
12671 for i in 1 .. currentApprovers.count loop
12672 if(ame_engine.approversMatch(approverRecord1In => currentApprovers(i),
12673 approverRecord2In => approverIn)) then
12674 approverInIndex := i;
12675 exit;
12676 end if;
12677 end loop;
12678 end if;
12679 /* Initialize the local variable approver. */
12680 if(approverInIndex is null) then
12681 ame_util.copyApproverRecord2(approverRecord2In => approverIn,
12682 approverRecord2Out => approver);
12683 else
12684 ame_util.copyApproverRecord2(approverRecord2In => currentApprovers(approverInIndex),
12685 approverRecord2Out => approver);
12686 approverOldApprovalStatus := approver.approval_status;
12687 approver.approval_status := approverIn.approval_status;
12688 end if;
12689 /*
12690 Most of the remaining code should reference approver rather than approverIn or
12691 currentApprovers(approverInIndex). Any code below this comment that cannot reference
12692 approver should have a comment explaining why.
12693 */
12694 /* Make sure the input approval statuses are valid. */
12695 if((approver.approver_category = ame_util.approvalApproverCategory and
12696 approver.approval_status not in (ame_util.approvedStatus,
12697 ame_util.approveAndForwardStatus,
12698 ame_util.forwardStatus,
12699 ame_util.rejectStatus,
12700 ame_util.noResponseStatus,
12701 ame_util.nullStatus,
12702 ame_util.notifiedStatus,
12703 ame_util2.reassignStatus) and
12704 approver.approval_status is not null) or
12705 (approver.approver_category = ame_util.fyiApproverCategory and
12706 approver.approval_status is not null and
12707 approver.approval_status <> ame_util.notifiedStatus)) then
12708 raise badStatusException;
12709 end if;
12710 /* Prepare forwardee (if any), if the forwarder is in the current list. */
12711 if(approver.approval_status in (ame_util.approveAndForwardStatus, ame_util.forwardStatus) and
12712 approverInIndex is not null) then
12713 /* Make sure a valid forwardee exists for forwardings. */
12714 if(forwardeeIn.name is null or
12715 forwardeeIn.name = approver.name) then
12716 raise badForwardeeException;
12717 end if;
12718 if(approver.source like (ame_util.specialForwardInsertion || '%')) then
12719 approverInIsSpecialForwardee := true;
12720 else
12721 approverInIsSpecialForwardee := false;
12722 end if;
12723 /* Copy forwardeeIn to forwardee. */
12724 ame_util.copyApproverRecord2(approverRecord2In => forwardeeIn,
12725 approverRecord2Out => forwardee);
12726 /* If approverInIsSpecialForwardee, silently convert api_insertion to
12727 ame_util.apiInsertion for forwardee */
12728 if approverInIsSpecialForwardee then
12729 forwardee.api_insertion := ame_util.apiInsertion;
12730 end if;
12731 /* Make sure the forwardee has the correct api_insertion value for COA forwarders. */
12732 if(/* Special forwardees can only do ad-hoc forwardings. */
12733 (approverInIsSpecialForwardee and
12734 forwardee.api_insertion <> ame_util.apiInsertion) or
12735 /* Ad-hoc approvers can only do ad-hoc forwardings. */
12736 ((not approverInIsSpecialForwardee and
12737 approver.authority <> ame_util.authorityApprover or
12738 approver.api_insertion = ame_util.apiInsertion) and
12739 forwardee.api_insertion <> ame_util.apiInsertion) or
12740 /* COA approvers other than special forwardees can only do COA forwardings. */
12741 (not approverInIsSpecialForwardee and
12742 approver.authority = ame_util.authorityApprover and
12743 approver.api_insertion <> ame_util.apiInsertion and
12744 forwardee.api_insertion <> ame_util.apiAuthorityInsertion)) then
12745 raise apiInsertionException;
12746 end if;
12747 /* Make sure forwardee has complete approver-matching data. */
12748 if(forwardee.orig_system is null or
12749 forwardee.orig_system_id is null or
12750 forwardee.display_name is null) then
12751 begin
12752 ame_approver_type_pkg.getOrigSystemIdAndDisplayName(nameIn =>forwardee.name,
12753 origSystemOut => forwardee.orig_system,
12754 origSystemIdOut => forwardee.orig_system_id,
12755 displayNameOut => forwardee.display_name);
12756 exception
12757 when others then
12758 l_error_code := sqlcode;
12759 if l_error_code = -20213 then
12760 errorCode := -20221;
12761 errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
12762 messageNameIn => 'AME_400837_INV_APR_FOUND',
12763 tokenNameOneIn => 'PROCESS_NAME',
12764 tokenValueOneIn => 'ame_engine.updateApprovalStatus',
12765 tokenNameTwoIn => 'NAME',
12766 tokenValueTwoIn => forwardee.name);
12767 raise_application_error(errorCode,errorMessage);
12768 end if;
12769 raise;
12770 end;
12771
12772 end if;
12773 /*
12774 If the forwardee is from a different originating system than the forwarder,
12775 make sure the forwardee is an ad-hoc insertion. Make this change silently,
12776 so calling applications don't have to be originating-system aware.
12777 */
12778 if(approver.orig_system <> forwardee.orig_system) then
12779 forwardee.api_insertion := ame_util.apiInsertion;
12780 end if;
12781 forwardee.item_class := approver.item_class;
12782 forwardee.item_id := approver.item_id;
12783 forwardee.authority := approver.authority;
12784 forwardee.action_type_id := approver.action_type_id;
12785 forwardee.group_or_chain_id := approver.group_or_chain_id;
12786 end if;
12787 /* Log the status update to the history table. */
12788 if(approverInIndex is null) then
12789 insert into ame_approvals_history(transaction_id,
12790 application_id,
12791 approval_status,
12792 row_timestamp,
12793 item_class,
12794 item_id,
12795 name,
12796 approver_category,
12797 action_type_id,
12798 group_or_chain_id,
12799 occurrence)
12800 values(transactionIdIn,
12801 ameApplicationId,
12802 decode(approver.approval_status,
12803 ame_util.nullStatus, ame_util.nullHistoryStatus,
12804 null, ame_util.nullHistoryStatus,
12805 approver.approval_status),
12806 sysdate,
12807 approver.item_class,
12808 approver.item_id,
12809 approver.name,
12810 approver.approver_category,
12811 ame_util.nullHistoryActionTypeId,
12812 ame_util.nullHistoryGroupOrChainId,
12813 ame_util.nullHistoryOccurrence);
12814 /* As approver is no longer in the approval list, log the message in the
12815 history table with a cleared date equal to sysdate. Also, first set
12816 date_cleared for other possible rows for this approver in the history
12817 table so that rows do not appear in the history table. */
12818 update AME_TRANS_APPROVAL_HISTORY
12819 set date_cleared = sysdate
12820 where transaction_id = transactionIdIn
12821 and application_id = ameApplicationId
12822 and name = approver.name
12823 and (approver.item_class is null or
12824 item_class = approver.item_class)
12825 and (approver.item_id is null or
12826 item_id = approver.item_id)
12827 and (approver.action_type_id is null or
12828 action_type_id = approver.action_type_id)
12829 and (approver.group_or_chain_id is null or
12830 group_or_chain_id = approver.group_or_chain_id)
12831 and (approver.occurrence is null or
12832 occurrence = approver.occurrence)
12833 and date_cleared is null;
12834 /* Log the approvers response in the Notification Approval History table before
12835 doing any further processing */
12836 insertIntoTransApprovalHistory
12837 (transactionIdIn => transactionIdIn
12838 ,applicationIdIn => ameApplicationId
12839 ,orderNumberIn => approver.approver_order_number
12840 ,nameIn => approver.name
12841 ,appCategoryIn => approver.approver_category
12842 ,itemClassIn => approver.item_class
12843 ,itemIdIn => approver.item_id
12844 ,actionTypeIdIn => ame_util.nullHistoryActionTypeId
12845 ,authorityIn => approver.authority
12846 ,statusIn => approver.approval_status
12847 ,grpOrChainIdIn => ame_util.nullHistoryGroupOrChainId
12848 ,occurrenceIn => ame_util.nullHistoryOccurrence
12849 ,apiInsertionIn => approver.api_insertion
12850 ,memberOrderNumberIn => approver.member_order_number
12851 ,notificationIdIn => notificationIn.notification_id
12852 ,userCommentsIn => notificationIn.user_comments
12853 ,dateClearedIn => sysdate
12854 ,historyTypeIn => 'APPROVERNOTPRESENT');
12855 /* Insert a warning into AME's exception log and return. */
12856 errorCode := -20001;
12857 errorMessage := ame_util.getMessage(applicationShortNameIn => 'PER',
12858 messageNameIn => 'AME_400065_API_NO_MATCH_APPR2');
12859 /*
12860 Pass localErrorIn => true in this case, because we're just logging a warning
12861 to the AME exception log, and we don't want the warning to appear in the
12862 Workflow context stack.
12863 */
12864 ame_util.runtimeException(packageNameIn => 'ame_engine',
12865 routineNameIn => 'updateApprovalStatus',
12866 exceptionNumberIn => errorCode,
12867 exceptionStringIn => errorMessage);
12868 return;
12869 end if;
12870 insert into ame_approvals_history(transaction_id,
12871 application_id,
12872 approval_status,
12873 row_timestamp,
12874 item_class,
12875 item_id,
12876 name,
12877 approver_category,
12878 action_type_id,
12879 group_or_chain_id,
12880 occurrence)
12881 values(transactionIdIn,
12882 ameApplicationId,
12883 decode(approver.approval_status,
12884 ame_util.nullStatus, ame_util.nullHistoryStatus,
12885 null, ame_util.nullHistoryStatus,
12886 approver.approval_status),
12887 sysdate,
12888 approver.item_class,
12889 approver.item_id,
12890 approver.name,
12891 approver.approver_category,
12892 approver.action_type_id,
12893 approver.group_or_chain_id,
12894 approver.occurrence);
12895 /*
12896 If the approver has been suppressed or is a repeated approver, disregard their response,
12897 even if they're trying to forward.
12898 */
12899 if(approverOldApprovalStatus in (ame_util.suppressedStatus, ame_util.beatByFirstResponderStatus, ame_util.repeatedStatus)) then
12900 /* The response though disregarded must be logged in the history table. This should not be shown in
12901 the history region. Hence set the date_cleared to sysdate. */
12902 insertIntoTransApprovalHistory
12903 (transactionIdIn => transactionIdIn
12904 ,applicationIdIn => ameApplicationId
12905 ,orderNumberIn => approver.approver_order_number
12906 ,nameIn => approver.name
12907 ,appCategoryIn => approver.approver_category
12908 ,itemClassIn => approver.item_class
12909 ,itemIdIn => approver.item_id
12910 ,actionTypeIdIn => approver.action_type_id
12911 ,authorityIn => approver.authority
12912 ,statusIn => approver.approval_status
12913 ,grpOrChainIdIn => approver.group_or_chain_id
12914 ,occurrenceIn => approver.occurrence
12915 ,apiInsertionIn => approver.api_insertion
12916 ,memberOrderNumberIn => approver.member_order_number
12917 ,notificationIdIn => notificationIn.notification_id
12918 ,userCommentsIn => notificationIn.user_comments
12919 ,dateClearedIn => sysdate
12920 ,historyTypeIn => 'APPROVERPRESENT');
12921 return;
12922 end if;
12923 /* Log the approvers response in the Notification Approval History table before
12924 doing any further processing */
12925 insertIntoTransApprovalHistory
12926 (transactionIdIn => transactionIdIn
12927 ,applicationIdIn => ameApplicationId
12928 ,orderNumberIn => approver.approver_order_number
12929 ,nameIn => approver.name
12930 ,appCategoryIn => approver.approver_category
12931 ,itemClassIn => approver.item_class
12932 ,itemIdIn => approver.item_id
12933 ,actionTypeIdIn => approver.action_type_id
12934 ,authorityIn => approver.authority
12935 ,statusIn => approver.approval_status
12936 ,grpOrChainIdIn => approver.group_or_chain_id
12937 ,occurrenceIn => approver.occurrence
12938 ,apiInsertionIn => approver.api_insertion
12939 ,memberOrderNumberIn => approver.member_order_number
12940 ,notificationIdIn => notificationIn.notification_id
12941 ,userCommentsIn => notificationIn.user_comments
12942 ,dateClearedIn => null
12943 ,historyTypeIn => 'APPROVERPRESENT');
12944 /*
12945 Update the status of approverIn in ame_temp_old_approver_lists. If updateItemIn
12946 is true, update also any other occurrences of the same approver for the same item
12947 class and item ID.
12948 */
12949 if(updateItemIn) then
12950 if(approver.approval_status in (ame_util.forwardStatus, ame_util.approveAndForwardStatus)) then
12951 /* Update the forwarder proper. */
12952 update ame_temp_old_approver_lists
12953 set approval_status = approver.approval_status
12954 where
12955 application_id = ameApplicationId and
12956 transaction_id = transactionIdIn and
12957 name = approver.name and
12958 item_class = approver.item_class and
12959 item_id = approver.item_id and
12960 action_type_id = approver.action_type_id and
12961 group_or_chain_id = approver.group_or_chain_id and
12962 occurrence = approver.occurrence;
12963 /* Suppress other occurrences of the approver, for the same item. */
12964 update ame_temp_old_approver_lists
12965 set approval_status = ame_util.suppressedStatus
12966 where
12967 application_id = ameApplicationId and
12968 transaction_id = transactionIdIn and
12969 name = approver.name and
12970 item_class = approver.item_class and
12971 item_id = approver.item_id and
12972 (action_type_id <> approver.action_type_id or
12973 group_or_chain_id <> approver.group_or_chain_id or
12974 occurrence <> approver.occurrence);
12975 else
12976 update ame_temp_old_approver_lists
12977 set approval_status = approver.approval_status
12978 where
12979 application_id = ameApplicationId and
12980 transaction_id = transactionIdIn and
12981 name = approver.name and
12982 item_class = approver.item_class and
12983 item_id = approver.item_id;
12984 end if;
12985 else
12986 update ame_temp_old_approver_lists
12987 set approval_status = approver.approval_status
12988 where
12989 application_id = ameApplicationId and
12990 transaction_id = transactionIdIn and
12991 name = approver.name and
12992 item_class = approver.item_class and
12993 item_id = approver.item_id and
12994 action_type_id = approver.action_type_id and
12995 group_or_chain_id = approver.group_or_chain_id and
12996 occurrence = approver.occurrence;
12997 end if;
12998 --+
12999 if approverInIndex is not null then
13000 setInsertedApprovalStatus(currentApproverIndexIn => approverInIndex
13001 ,approvalStatusIn => approver.approval_status);
13002 end if;
13003 if approver.approval_status in (ame_util.approvedStatus
13004 ,ame_util.rejectStatus
13005 ,ame_util.approveAndForwardStatus
13006 ,ame_util.forwardStatus
13007 ,ame_util.noResponseStatus) then
13008 for z in 1 .. repeatedIndexes.count loop
13009 if repeatedIndexes(z) = approverInIndex and repeatedAppIndexes(z) <> approverInIndex then
13010 update ame_temp_old_approver_lists
13011 set approval_status = decode(approver.approval_status
13012 ,ame_util.approvedStatus
13013 ,ame_util.approvedByRepeatedStatus
13014 ,ame_util.approveAndForwardStatus
13015 ,ame_util.approvedByRepeatedStatus
13016 ,ame_util.rejectStatus
13017 ,ame_util.rejectedByRepeatedStatus
13018 ,ame_util.forwardStatus
13019 ,ame_util2.forwardByRepeatedStatus
13020 ,ame_util2.reassignStatus
13021 ,ame_util.nullStatus
13022 ,ame_util.noResponseStatus
13023 ,ame_util2.noResponseByRepeatedStatus
13024 ,ame_util.repeatedStatus)
13025 where application_id = ameApplicationId
13026 and transaction_id = transactionIdIn
13027 and name = approver.name
13028 and item_class = currentApprovers(repeatedAppIndexes(z)).item_class
13029 and item_id = currentApprovers(repeatedAppIndexes(z)).item_id
13030 and action_type_id = currentApprovers(repeatedAppIndexes(z)).action_type_id
13031 and group_or_chain_id = currentApprovers(repeatedAppIndexes(z)).group_or_chain_id
13032 and occurrence = currentApprovers(repeatedAppIndexes(z)).occurrence
13033 and approval_status in ( ame_util.notifiedByRepeatedStatus
13034 ,ame_util.repeatedStatus);
13035 select decode(approver.approval_status
13036 ,ame_util.approvedStatus
13037 ,ame_util.approvedByRepeatedStatus
13038 ,ame_util.approveAndForwardStatus
13039 ,ame_util.approvedByRepeatedStatus
13040 ,ame_util.rejectStatus
13041 ,ame_util.rejectedByRepeatedStatus
13042 ,ame_util.forwardStatus
13043 ,ame_util2.forwardByRepeatedStatus
13044 ,ame_util2.reassignStatus
13045 ,ame_util.nullStatus
13046 ,ame_util.noResponseStatus
13047 ,ame_util2.noResponseByRepeatedStatus
13048 ,ame_util.repeatedStatus) into tempStatus from dual;
13049 setInsertedApprovalStatus(currentApproverIndexIn => repeatedAppIndexes(z)
13050 ,approvalStatusIn => tempStatus);
13051 l_frw_index := repeatedAppIndexes(z);
13052 l_actionTypeId := currentApprovers(l_frw_index).action_type_id;
13053 l_votingRegime := null;
13054 l_votingRegime := ame_engine.getActionTypeVotingRegime(l_actionTypeId);
13055 if l_votingRegime is null then
13056 l_votingRegime := ame_approval_group_pkg.getVotingRegime(
13057 approvalGroupIdIn => currentApprovers(l_frw_index).group_or_chain_id ,
13058 applicationIdIn => ameApplicationId);
13059 end if;
13060 if l_votingRegime = ame_util.firstApproverVoting then
13061 tempfrwCount := 0;
13062 select count(*)
13063 into tempfrwCount
13064 from ame_temp_old_approver_lists
13065 where
13066 application_id = ameApplicationId and
13067 transaction_id = transactionIdIn and
13068 item_class = currentApprovers(l_frw_index).item_class and
13069 item_id = currentApprovers(l_frw_index).item_id and
13070 action_type_id = currentApprovers(l_frw_index).action_type_id and
13071 group_or_chain_id = currentApprovers(l_frw_index).group_or_chain_id and
13072 approver_category = ame_util.approvalApproverCategory and
13073 approval_status in (ame_util.notifiedStatus
13074 ,ame_util.notifiedByRepeatedStatus) and
13075 exists ( select null
13076 from ame_temp_old_approver_lists
13077 where application_id = ameApplicationId and
13078 transaction_id = transactionIdIn and
13079 item_class = currentApprovers(l_frw_index).item_class and
13080 item_id = currentApprovers(l_frw_index).item_id and
13081 action_type_id = currentApprovers(l_frw_index).action_type_id and
13082 group_or_chain_id = currentApprovers(l_frw_index).group_or_chain_id and
13083 approver_category = ame_util.approvalApproverCategory and
13084 approval_status in (ame_util.approvedStatus
13085 ,ame_util.approvedByRepeatedStatus
13086 ,ame_util.rejectStatus
13087 ,ame_util.rejectedByRepeatedStatus)
13088 ) and
13089 not exists ( select null
13090 from ame_temp_old_approver_lists
13091 where application_id = ameApplicationId and
13092 transaction_id = transactionIdIn and
13093 item_class = currentApprovers(l_frw_index).item_class and
13094 item_id = currentApprovers(l_frw_index).item_id and
13095 action_type_id = currentApprovers(l_frw_index).action_type_id and
13096 group_or_chain_id = currentApprovers(l_frw_index).group_or_chain_id and
13097 approver_category = ame_util.approvalApproverCategory and
13098 (approval_status is null or approval_status in (
13099 ame_util.nullStatus
13100 ,ame_util.repeatedStatus)));
13101 if tempfrwCount > 0 then
13102 update ame_temp_old_approver_lists
13103 set approval_status = ame_util.beatByFirstResponderStatus
13104 where
13105 application_id = ameApplicationId and
13106 transaction_id = transactionIdIn and
13107 item_class = currentApprovers(l_frw_index).item_class and
13108 item_id = currentApprovers(l_frw_index).item_id and
13109 action_type_id = currentApprovers(l_frw_index).action_type_id and
13110 group_or_chain_id = currentApprovers(l_frw_index).group_or_chain_id and
13111 approver_category = ame_util.approvalApproverCategory and
13112 approval_status in (ame_util.notifiedStatus,ame_util.notifiedByRepeatedStatus );
13113 insertIntoTransApprovalHistory
13114 (transactionIdIn => transactionIdIn
13115 ,applicationIdIn => ameApplicationId
13116 ,orderNumberIn => currentApprovers(l_frw_index).approver_order_number
13117 ,nameIn => currentApprovers(l_frw_index).name
13118 ,appCategoryIn => null
13119 ,itemClassIn => currentApprovers(l_frw_index).item_class
13120 ,itemIdIn => currentApprovers(l_frw_index).item_id
13121 ,actionTypeIdIn => currentApprovers(l_frw_index).action_type_id
13122 ,authorityIn => null
13123 ,statusIn => null
13124 ,grpOrChainIdIn => currentApprovers(l_frw_index).group_or_chain_id
13125 ,occurrenceIn => currentApprovers(l_frw_index).occurrence
13126 ,apiInsertionIn => currentApprovers(l_frw_index).api_insertion
13127 ,memberOrderNumberIn => currentApprovers(l_frw_index).member_order_number
13128 ,notificationIdIn => notificationIn.notification_id
13129 ,userCommentsIn => null
13130 ,dateClearedIn => null
13131 ,historyTypeIn => 'BEATBYFIRSTRESPONDER');
13132 end if;
13133 end if;
13134 end if;
13135 end loop;
13136 end if;
13137 if(approver.approval_status is null or approver.approval_status in (ame_util.approvedStatus, ame_util.rejectStatus )) then
13138 /* Account for approval-group and chain-of-authority voting. */
13139 /* get action type id's for ame_util.groupChainApprovalTypeName,
13140 ame_util.postApprovalTypeName and ame_util.preApprovalTypeName */
13141 tempCOAGroupActionTypeId := ame_action_pkg.getActionTypeIdByName(actionTypeNameIn =>
13142 ame_util.groupChainApprovalTypeName);
13143 tempPreGroupActionTypeId := ame_action_pkg.getActionTypeIdByName(actionTypeNameIn =>
13144 ame_util.preApprovalTypeName);
13145 tempPostGroupActionTypeId := ame_action_pkg.getActionTypeIdByName(actionTypeNameIn =>
13146 ame_util.postApprovalTypeName);
13147 if approver.action_type_id in (tempPreGroupActionTypeId
13148 ,tempPostGroupActionTypeId) then
13149 -- removed tempCOAGroupActionTypeId from above list for the
13150 -- bug 4095605
13151 votingRegime := ame_approval_group_pkg.getVotingRegime(
13152 approvalGroupIdIn => approver.group_or_chain_id ,
13153 applicationIdIn => ameApplicationId);
13154 -- in approver.group_or_chain_id
13155 else
13156 votingRegime := ame_engine.getActionTypeVotingRegime(actionTypeIdIn => approver.action_type_id);
13157 end if;
13158 if(votingRegime = ame_util.firstApproverVoting) then
13159 if approver.approval_status in (ame_util.approvedStatus, ame_util.rejectStatus ) then
13160 /*
13161 approverIn must be the first responder (otherwise, they would be suppressed,
13162 and we would have returned above). Suppress the other approval approvers in the
13163 group or chain (including other occurrences of the input approver).
13164 */
13165 update ame_temp_old_approver_lists
13166 set approval_status = ame_util.beatByFirstResponderStatus
13167 where
13168 application_id = ameApplicationId and
13169 transaction_id = transactionIdIn and
13170 (name <> approver.name or
13171 occurrence <> approver.occurrence) and
13172 item_class = approver.item_class and
13173 item_id = approver.item_id and
13174 action_type_id = approver.action_type_id and
13175 group_or_chain_id = approver.group_or_chain_id and
13176 approver_category = ame_util.approvalApproverCategory and
13177 approval_status in (ame_util.notifiedStatus,ame_util.notifiedByRepeatedStatus);
13178 for i in 1..currentApprovers.count loop
13179 if currentApprovers(i).item_class = approver.item_class and
13180 currentApprovers(i).item_id = approver.item_id and
13181 currentApprovers(i).action_type_id = approver.action_type_id and
13182 currentApprovers(i).group_or_chain_id = approver.group_or_chain_id and
13183 currentApprovers(i).approver_category = approver.approver_category and
13184 currentApprovers(i).approval_status = ame_util.notifiedStatus and
13185 (currentApprovers(i).name <> approver.name or
13186 currentApprovers(i).occurrence <> approver.occurrence) then
13187 setInsertedApprovalStatus(currentApproverIndexIn => i
13188 ,approvalStatusIn => ame_util.beatByFirstResponderStatus);
13189 end if;
13190 end loop;
13191 /* Insert rows in the notification approval history region for approvers
13192 with beat by first responder */
13193 insertIntoTransApprovalHistory
13194 (transactionIdIn => transactionIdIn
13195 ,applicationIdIn => ameApplicationId
13196 ,orderNumberIn => approver.approver_order_number
13197 ,nameIn => approver.name
13198 ,appCategoryIn => null
13199 ,itemClassIn => approver.item_class
13200 ,itemIdIn => approver.item_id
13201 ,actionTypeIdIn => approver.action_type_id
13202 ,authorityIn => null
13203 ,statusIn => null
13204 ,grpOrChainIdIn => approver.group_or_chain_id
13205 ,occurrenceIn => approver.occurrence
13206 ,apiInsertionIn => approver.api_insertion
13207 ,memberOrderNumberIn => approver.member_order_number
13208 ,notificationIdIn => notificationIn.notification_id
13209 ,userCommentsIn => null
13210 ,dateClearedIn => null
13211 ,historyTypeIn => 'BEATBYFIRSTRESPONDER');
13212 elsif approver.approval_status is null then
13213 /*
13214 the approval status is null. This is the request to clear the approval status.
13215 As this approver is from a FRW approver group, need to clear the status of all the group members.
13216 */
13217 update ame_temp_old_approver_lists
13218 set approval_status = null
13219 where
13220 application_id = ameApplicationId and
13221 transaction_id = transactionIdIn and
13222 (name <> approver.name or
13223 occurrence <> approver.occurrence) and
13224 item_class = approver.item_class and
13225 item_id = approver.item_id and
13226 action_type_id = approver.action_type_id and
13227 group_or_chain_id = approver.group_or_chain_id and
13228 approver_category = ame_util.approvalApproverCategory;
13229 -- and approval_status in (ame_util.notifiedStatus,ame_util.notifiedByRepeatedStatus);
13230 insertIntoTransApprovalHistory
13231 (transactionIdIn => transactionIdIn
13232 ,applicationIdIn => ameApplicationId
13233 ,orderNumberIn => approver.approver_order_number
13234 ,nameIn => approver.name
13235 ,appCategoryIn => approver.approver_category
13236 ,itemClassIn => approver.item_class
13237 ,itemIdIn => approver.item_id
13238 ,actionTypeIdIn => approver.action_type_id
13239 ,authorityIn => approver.authority
13240 ,statusIn => approver.approval_status
13241 ,grpOrChainIdIn => approver.group_or_chain_id
13242 ,occurrenceIn => approver.occurrence
13243 ,apiInsertionIn => approver.api_insertion
13244 ,memberOrderNumberIn => approver.member_order_number
13245 ,notificationIdIn => notificationIn.notification_id
13246 ,userCommentsIn => notificationIn.user_comments
13247 ,dateClearedIn => null
13248 ,historyTypeIn => 'CLEARFRWGRP');
13249 end if;
13250 end if;
13251 end if;
13252 --+
13253 --+ process reassignStatus
13254 --+
13255 if(approver.approval_status = ame_util2.reassignStatus) then
13256 ame_util.copyApproverRecord2(approverRecord2In => forwardeeIn,
13257 approverRecord2Out => forwardee);
13258 -- fetch forwardee details
13259 if(forwardee.orig_system is null or
13260 forwardee.orig_system_id is null or
13261 forwardee.display_name is null) then
13262
13263 begin
13264 ame_approver_type_pkg.getOrigSystemIdAndDisplayName(nameIn =>forwardee.name,
13265 origSystemOut => forwardee.orig_system,
13266 origSystemIdOut => forwardee.orig_system_id,
13267 displayNameOut => forwardee.display_name);
13268 exception
13269 when others then
13270 l_error_code := sqlcode;
13271 if l_error_code = -20213 then
13272 errorCode := -20221;
13273 errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
13274 messageNameIn => 'AME_400837_INV_APR_FOUND',
13275 tokenNameOneIn => 'PROCESS_NAME',
13276 tokenValueOneIn => 'ame_engine.updateApprovalStatus',
13277 tokenNameTwoIn => 'NAME',
13278 tokenValueTwoIn => forwardee.name);
13279 raise_application_error(errorCode,errorMessage);
13280 end if;
13281 raise;
13282 end;
13283 end if;
13284 tempInsertionOrder := ame_engine.getNextInsertionOrder;
13285 tempParameter := approver.name ||
13286 ame_util.fieldDelimiter ||
13287 approver.item_class ||
13288 ame_util.fieldDelimiter ||
13289 approver.item_id ||
13290 ame_util.fieldDelimiter ||
13291 approver.action_type_id ||
13292 ame_util.fieldDelimiter ||
13293 approver.group_or_chain_id ||
13294 ame_util.fieldDelimiter ||
13295 approver.occurrence;
13296 insert into ame_temp_insertions(
13297 transaction_id,
13298 application_id,
13299 insertion_order,
13300 order_type,
13301 parameter,
13302 description,
13303 name,
13304 item_class,
13305 item_id,
13306 approver_category,
13307 api_insertion,
13308 authority,
13309 effective_date,
13310 reason) values(
13311 transactionIdIn,
13312 ameApplicationId,
13313 tempInsertionOrder,
13314 ame_util.afterApprover,
13315 tempParameter,
13316 ame_util.afterApproverDescription || approver.display_name,
13317 forwardee.name,
13318 forwardee.item_class,
13319 forwardee.item_id,
13320 forwardee.approver_category,
13321 decode(forwarderType,
13322 ame_util.chainOfAuthorityForwarder, ame_util.apiAuthorityInsertion,
13323 ame_util.apiInsertion),
13324 approver.authority,
13325 sysdate,
13326 ame_approver_deviation_pkg.reassignStatus );
13327 end if;
13328 --+
13329 /* Process the forwardee, checking for special forwarding cases. */
13330 if(approver.approval_status in (ame_util.forwardStatus,
13331 ame_util.approveAndForwardStatus)) then
13332 forwardeeType := null;
13333 if(approverInIsSpecialForwardee or
13334 approver.authority <> ame_util.authorityApprover or
13335 approver.api_insertion = ame_util.apiInsertion) then
13336 forwarderType := ame_util.adHocForwarder;
13337 else
13338 forwarderType := ame_util.chainOfAuthorityForwarder;
13339 end if;
13340 /* Use the reverse keyword to find the match nearest to approver. */
13341 for i in reverse 1 .. approverInIndex loop
13342 if(currentApprovers(i).name = forwardee.name and currentApprovers(i).item_id=approver.item_id) then
13343 forwardeeIndex := i;
13344 if(forwarderType = ame_util.chainOfAuthorityForwarder and
13345 currentApprovers(i).action_type_id = forwardee.action_type_id and
13346 currentApprovers(i).group_or_chain_id = forwardee.group_or_chain_id) then
13347 forwardeeType := ame_util.previousSameChainForwardee;
13348 else
13349 forwardeeType := ame_util.alreadyInListForwardee;
13350 end if;
13351 exit;
13352 end if;
13353 end loop;
13354 if(forwarderType = ame_util.chainOfAuthorityForwarder and
13355 (forwardeeType is null or
13356 forwardeeType = ame_util.alreadyInListForwardee) and
13357 ame_approver_type_pkg.isASubordinate(approverIn => approver,
13358 possibleSubordApproverIn => forwardee)) then
13359 forwardeeType := ame_util.subordSameHierarchyForwardee;
13360 end if;
13361 if(forwardeeType = ame_util.previousSameChainForwardee) then
13362 forwardee.occurrence := currentApprovers(forwardeeIndex).occurrence + 1;
13363 else
13364 forwardee.occurrence := 1;
13365 end if;
13366 if(forwardeeType is null) then /* Handle normal forwarding cases. */
13367 if(approver.orig_system <> forwardee.orig_system) then
13368 forwarderType := ame_util.adHocForwarder;
13369 end if;
13370 tempInsertionOrder := ame_engine.getNextInsertionOrder;
13371 tempParameter := approver.name ||
13372 ame_util.fieldDelimiter ||
13373 approver.item_class ||
13374 ame_util.fieldDelimiter ||
13375 approver.item_id ||
13376 ame_util.fieldDelimiter ||
13377 approver.action_type_id ||
13378 ame_util.fieldDelimiter ||
13379 approver.group_or_chain_id ||
13380 ame_util.fieldDelimiter ||
13381 approver.occurrence;
13382 insert into ame_temp_insertions(
13383 transaction_id,
13384 application_id,
13385 insertion_order,
13386 order_type,
13387 parameter,
13388 description,
13389 name,
13390 item_class,
13391 item_id,
13392 approver_category,
13393 api_insertion,
13394 authority,
13395 effective_date,
13396 reason) values(
13397 transactionIdIn,
13398 ameApplicationId,
13399 tempInsertionOrder,
13400 ame_util.afterApprover,
13401 tempParameter,
13402 ame_util.afterApproverDescription || approver.display_name,
13403 forwardee.name,
13404 forwardee.item_class,
13405 forwardee.item_id,
13406 forwardee.approver_category,
13407 decode(forwarderType,
13408 ame_util.chainOfAuthorityForwarder, ame_util.apiAuthorityInsertion,
13409 ame_util.apiInsertion),
13410 approver.authority,
13411 sysdate
13412 ,ame_approver_deviation_pkg.forwardReason );
13413 else /* Handle special forwarding cases. */
13414 /*
13415 All of the insertees generated within this if statement should have the same
13416 action_type_id and group_or_chain_id as approver. The insertees' source
13417 should always be ame_util.specialForwardInsertion. The insertions' order
13418 types should always be ame_util.afterApprover.
13419 */
13420 forwardingBehavior := ame_engine.getForwardingBehavior(forwarderTypeIn => forwarderType,
13421 forwardeeTypeIn => forwardeeType,
13422 approvalStatusIn => approver.approval_status);
13423 if(forwardingBehavior in (ame_util.repeatForwarder,
13424 ame_util.skipForwarder,
13425 ame_util.remand)) then
13426 /*
13427 Locate the start of the chain, so we can calculate each insertee's occurrence
13428 value, for use in the following insertee's insertion parameter.
13429 */
13430 for i in reverse 1 .. (approverInIndex - 1) loop
13431 if(currentApprovers(i).group_or_chain_id <> approver.group_or_chain_id or
13432 currentApprovers(i).action_type_id <> approver.action_type_id or
13433 currentApprovers(i).item_id <> approver.item_id or
13434 currentApprovers(i).item_class <> approver.item_class) then
13435 firstIndexInChain := i + 1;
13436 exit;
13437 end if;
13438 end loop;
13439 if(firstIndexInChain is null) then
13440 firstIndexInChain := 1;
13441 end if;
13442 end if;
13443 /* Handle the special forwarding cases. */
13444 if(forwardingBehavior in (ame_util.forwardeeOnly,
13445 ame_util.forwarderAndForwardee)) then
13446 /* Insert forwardee as ad-hoc or COA, according to whether approverIn is ad-hoc or COA. */
13447 tempInsertionOrder := ame_engine.getNextInsertionOrder;
13448 tempParameter := approver.name ||
13449 ame_util.fieldDelimiter ||
13450 approver.item_class ||
13451 ame_util.fieldDelimiter ||
13452 approver.item_id ||
13453 ame_util.fieldDelimiter ||
13454 approver.action_type_id ||
13455 ame_util.fieldDelimiter ||
13456 approver.group_or_chain_id ||
13457 ame_util.fieldDelimiter ||
13458 approver.occurrence;
13459 insert into ame_temp_insertions(
13460 transaction_id,
13461 application_id,
13462 insertion_order,
13463 order_type,
13464 parameter,
13465 description,
13466 name,
13467 item_class,
13468 item_id,
13469 approver_category,
13470 api_insertion,
13471 authority,
13472 special_forwardee,
13473 effective_date,
13474 reason) values(
13475 transactionIdIn,
13476 ameApplicationId,
13477 tempInsertionOrder,
13478 ame_util.afterApprover,
13479 tempParameter,
13480 ame_util.afterApproverDescription || approver.display_name,
13481 forwardee.name,
13482 forwardee.item_class,
13483 forwardee.item_id,
13484 ame_util.approvalApproverCategory, /* Forwarding is not possible from an FYI approver. */
13485 decode(forwarderType,
13486 ame_util.chainOfAuthorityForwarder, ame_util.apiAuthorityInsertion,
13487 ame_util.apiInsertion),
13488 approver.authority,
13489 ame_util.booleanTrue,
13490 sysdate,
13491 ame_approver_deviation_pkg.forwardReason);
13492 if(forwardingBehavior = ame_util.forwarderAndForwardee) then /* Insert the forwarder. */
13493 tempInsertionOrder := ame_engine.getNextInsertionOrder;
13494 tempParameter := forwardee.name ||
13495 ame_util.fieldDelimiter ||
13496 forwardee.item_class ||
13497 ame_util.fieldDelimiter ||
13498 forwardee.item_id ||
13499 ame_util.fieldDelimiter ||
13500 forwardee.action_type_id ||
13501 ame_util.fieldDelimiter ||
13502 forwardee.group_or_chain_id ||
13503 ame_util.fieldDelimiter ||
13504 forwardee.occurrence;
13505 insert into ame_temp_insertions(
13506 transaction_id,
13507 application_id,
13508 insertion_order,
13509 order_type,
13510 parameter,
13511 description,
13512 name,
13513 item_class,
13514 item_id,
13515 approver_category,
13516 api_insertion,
13517 authority,
13518 special_forwardee,
13519 effective_date,
13520 reason) values(
13521 transactionIdIn,
13522 ameApplicationId,
13523 tempInsertionOrder,
13524 ame_util.afterApprover,
13525 tempParameter,
13526 ame_util.afterApproverDescription || forwardee.display_name,
13527 approver.name,
13528 approver.item_class,
13529 approver.item_id,
13530 ame_util.approvalApproverCategory, /* Forwarding is not possible from an FYI approver. */
13531 decode(forwarderType,
13532 ame_util.chainOfAuthorityForwarder, ame_util.apiAuthorityInsertion,
13533 ame_util.apiInsertion),
13534 approver.authority,
13535 ame_util.booleanTrue,
13536 sysdate,
13537 ame_approver_deviation_pkg.forwardForwardeeReason);
13538 end if;
13539 elsif(forwardingBehavior in (ame_util.repeatForwarder, ame_util.skipForwarder)) then
13540 /*
13541 These cases are for a forwardee who is a subordinate of approverIn (who must be
13542 a COA approver), but who does not already precede approverIn in the list. In this
13543 case we insert starting at the insertee, and ascending the hierarchy up to but not
13544 including approver. In the case of ame_util.repeatForwarder, we then add
13545 approverIn and stop. In the case of ame_util.skipForwarder, we then add
13546 approverIn's superior and stop. The insertees are all COA approvers.
13547 */
13548 /* Insert the forwardee. */
13549 tempInsertionOrder := ame_engine.getNextInsertionOrder;
13550 tempParameter := approver.name ||
13551 ame_util.fieldDelimiter ||
13552 approver.item_class ||
13553 ame_util.fieldDelimiter ||
13554 approver.item_id ||
13555 ame_util.fieldDelimiter ||
13556 approver.action_type_id ||
13557 ame_util.fieldDelimiter ||
13558 approver.group_or_chain_id ||
13559 ame_util.fieldDelimiter ||
13560 approver.occurrence;
13561 insert into ame_temp_insertions(
13562 transaction_id,
13563 application_id,
13564 insertion_order,
13565 order_type,
13566 parameter,
13567 description,
13568 name,
13569 item_class,
13570 item_id,
13571 approver_category,
13572 api_insertion,
13573 authority,
13574 special_forwardee,
13575 effective_date,
13576 reason) values(
13577 transactionIdIn,
13578 ameApplicationId,
13579 tempInsertionOrder,
13580 ame_util.afterApprover,
13581 tempParameter,
13582 ame_util.afterApproverDescription || approver.display_name,
13583 forwardee.name,
13584 forwardee.item_class,
13585 forwardee.item_id,
13586 ame_util.approvalApproverCategory, /* Forwarding is not possible from an FYI approver. */
13587 ame_util.apiAuthorityInsertion,
13588 ame_util.authorityApprover,
13589 ame_util.booleanTrue,
13590 sysdate,
13591 ame_approver_deviation_pkg.forwardReason);
13592 insertedApprover.name := forwardee.name;
13593 insertedApprover.orig_system := forwardee.orig_system;
13594 insertedApprover.orig_system_id := forwardee.orig_system_id;
13595 insertedApprover.item_class := forwardee.item_class;
13596 insertedApprover.item_id := forwardee.item_id;
13597 insertedApprover.action_type_id := forwardee.action_type_id;
13598 insertedApprover.group_or_chain_id :=forwardee.group_or_chain_id;
13599 insertedApprover.occurrence := forwardee.occurrence;
13600 forwarderFound := false;
13601 /* Iterate through the forwardee's chain of authority. */
13602 loop
13603 /* Get the next superior to insert. */
13604 tempReason := ame_approver_deviation_pkg.forwardEngInsReason;
13605 ame_approver_type_pkg.getSuperior(approverIn => insertedApprover,
13606 superiorOut => superiorApprover);
13607 if(superiorApprover.name = approver.name) then
13608 forwarderFound := true;
13609 tempReason := ame_approver_deviation_pkg.forwardForwardeeReason;
13610 if(forwardingBehavior = ame_util.skipForwarder) then
13611 tempReason := ame_approver_deviation_pkg.forwardEngInsReason;
13612 --insertedApprover.name := approver.name;
13613 --insertedApprover.orig_system_id := approver.orig_system_id;
13614 ame_approver_type_pkg.getSuperior(approverIn => approver,
13615 superiorOut => superiorApprover);
13616 end if;
13617 end if;
13618 /* Calculate insertedApprover.occurrence. */
13619 insertedApprover.occurrence := 1;
13620 for i in reverse firstIndexInChain .. approverInIndex loop
13621 if(currentApprovers(i).name = insertedApprover.name) then
13622 insertedApprover.occurrence := currentApprovers(i).occurrence + 1;
13623 exit;
13624 end if;
13625 end loop;
13626 /* Prepare and do the insertion. */
13627 tempInsertionOrder := ame_engine.getNextInsertionOrder;
13628 tempParameter := insertedApprover.name ||
13629 ame_util.fieldDelimiter ||
13630 insertedApprover.item_class ||
13631 ame_util.fieldDelimiter ||
13632 insertedApprover.item_id ||
13633 ame_util.fieldDelimiter ||
13634 insertedApprover.action_type_id ||
13635 ame_util.fieldDelimiter ||
13636 insertedApprover.group_or_chain_id ||
13637 ame_util.fieldDelimiter ||
13638 insertedApprover.occurrence;
13639 insert into ame_temp_insertions(
13640 transaction_id,
13641 application_id,
13642 insertion_order,
13643 order_type,
13644 parameter,
13645 description,
13646 name,
13647 item_class,
13648 item_id,
13649 approver_category,
13650 api_insertion,
13651 authority,
13652 special_forwardee,
13653 effective_date,
13654 reason) values(
13655 transactionIdIn,
13656 ameApplicationId,
13657 tempInsertionOrder,
13658 ame_util.afterApprover,
13659 tempParameter,
13660 ame_util.afterApproverDescription || insertedApprover.display_name,
13661 superiorApprover.name,
13662 approver.item_class,
13663 approver.item_id,
13664 ame_util.approvalApproverCategory, /* Forwarding is not possible from an FYI approver. */
13665 ame_util.apiAuthorityInsertion,
13666 ame_util.authorityApprover,
13667 ame_util.booleanTrue,
13668 sysdate,
13669 tempReason);
13670 if(forwarderFound) then
13671 exit;
13672 end if;
13673 insertedApprover.name := superiorApprover.name;
13674 insertedApprover.orig_system_id := superiorApprover.orig_system_id;
13675 end loop;
13676 elsif(forwardingBehavior = ame_util.remand) then
13677 /*
13678 Remanding is possible only when forwardeeIn already precedes approverIn in
13679 the list (not necessarily in the same chain), and approverIn is a COA approver. In
13680 such cases, we insert starting with forwardeeIn and continuing up to and including
13681 approver. The insertees are always ad-hoc, and pertain to the same item, sublist,
13682 action type, and group or chain as the forwarder.
13683 */
13684 for i in forwardeeIndex .. approverInIndex loop
13685 if(i = forwardeeIndex) then
13686 prevApproverIndex := approverInIndex;
13687 prevApproverOccurrence := approver.occurrence;
13688 else
13689 prevApproverIndex := i - 1;
13690 prevApproverOccurrence := 1;
13691 for i in reverse firstIndexInChain .. approverInIndex loop
13692 if(currentApprovers(i).name = currentApprovers(prevApproverIndex).name) then
13693 prevApproverOccurrence := currentApprovers(prevApproverIndex).occurrence + 1;
13694 exit;
13695 end if;
13696 end loop;
13697 end if;
13698 tempInsertionOrder := ame_engine.getNextInsertionOrder;
13699 tempParameter := currentApprovers(prevApproverIndex).name ||
13700 ame_util.fieldDelimiter ||
13701 approver.item_class ||
13702 ame_util.fieldDelimiter ||
13703 approver.item_id ||
13704 ame_util.fieldDelimiter ||
13705 approver.action_type_id ||
13706 ame_util.fieldDelimiter ||
13707 approver.group_or_chain_id ||
13708 ame_util.fieldDelimiter ||
13709 prevApproverOccurrence;
13710 insert into ame_temp_insertions(
13711 transaction_id,
13712 application_id,
13713 insertion_order,
13714 order_type,
13715 parameter,
13716 description,
13717 name,
13718 item_class,
13719 item_id,
13720 approver_category,
13721 api_insertion,
13722 authority,
13723 special_forwardee,
13724 effective_date,
13725 reason) values(
13726 transactionIdIn,
13727 ameApplicationId,
13728 tempInsertionOrder,
13729 ame_util.afterApprover,
13730 tempParameter,
13731 ame_util.afterApproverDescription || insertedApprover.display_name,
13732 currentApprovers(i).name,
13733 approver.item_class,
13734 approver.item_id,
13735 ame_util.approvalApproverCategory, /* Forwarding is not possible from an FYI approver. */
13736 ame_util.apiInsertion,
13737 approver.authority,
13738 ame_util.booleanTrue,
13739 sysdate,
13740 ame_approver_deviation_pkg.forwardRemandReason);
13741 prevApproverIndex := prevApproverIndex + 1;
13742 end loop;
13743 /* else forwardingBehavior = ame_util.ignoreForwarding */
13744 end if;
13745 end if;
13746 /* Cycle the engine to write the forwardees out to the old-approvers table. */
13747 ame_engine.updateTransactionState(isTestTransactionIn => false,
13748 isLocalTransactionIn => false,
13749 fetchConfigVarsIn => true,
13750 fetchOldApproversIn => true,
13751 fetchInsertionsIn => true,
13752 fetchDeletionsIn => true,
13753 fetchAttributeValuesIn => true,
13754 fetchInactiveAttValuesIn => false,
13755 processProductionActionsIn => false,
13756 processProductionRulesIn => false,
13757 updateCurrentApproverListIn => true,
13758 updateOldApproverListIn => true,
13759 processPrioritiesIn => true,
13760 prepareItemDataIn => false,
13761 prepareRuleIdsIn => false,
13762 prepareRuleDescsIn => false,
13763 transactionIdIn => transactionIdIn,
13764 ameApplicationIdIn => null,
13765 fndApplicationIdIn => applicationIdIn,
13766 transactionTypeIdIn => transactionTypeIn);
13767 end if;
13768 ame_engine.unlockTransaction(fndApplicationIdIn => applicationIdIn,
13769 transactionIdIn => transactionIdIn,
13770 transactionTypeIdIn => transactionTypeIn);
13771 exception
13772 when badForwardeeException then
13773 ame_engine.unlockTransaction(fndApplicationIdIn => applicationIdIn,
13774 transactionIdIn => transactionIdIn,
13775 transactionTypeIdIn => transactionTypeIn);
13776 errorCode := -20101;
13777 if transactionTypeIn is not null then
13778 errorMessage := ame_util.getMessage(applicationShortNameIn => 'PER',
13779 messageNameIn => 'AME_400298_API_FOR_NOT_VALID',
13780 tokenNameOneIn => 'TRANSACTION_ID',
13781 tokenValueOneIn => transactionIdIn,
13782 tokenNameTwoIn => 'TRANSACTION_TYPE',
13783 tokenValueTwoIn => transactionTypeIn);
13784 else
13785 errorMessage := ame_util.getMessage(applicationShortNameIn => 'PER',
13786 messageNameIn => 'AME_400066_API_FOR_NOT_VALID2',
13787 tokenNameOneIn => 'TRANSACTION_ID',
13788 tokenValueOneIn => transactionIdIn);
13789 end if;
13790 ame_util.runtimeException(packageNameIn => 'ame_engine',
13791 routineNameIn => 'updateApprovalStatus',
13792 exceptionNumberIn => errorCode,
13793 exceptionStringIn => errorMessage);
13794 raise_application_error(errorCode,
13795 errorMessage);
13796 when apiInsertionException then
13797 ame_engine.unlockTransaction(fndApplicationIdIn => applicationIdIn,
13798 transactionIdIn => transactionIdIn,
13799 transactionTypeIdIn => transactionTypeIn);
13800 errorCode := -20308;
13801 errorMessage :=
13802 ame_util.getMessage(applicationShortNameIn => 'PER',
13803 messageNameIn => 'AME_400246_API_FWD_SAME_VALUE');
13804 ame_util.runtimeException(packageNameIn => 'ame_engine',
13805 routineNameIn => 'updateApprovalStatus',
13806 exceptionNumberIn => errorCode,
13807 exceptionStringIn => errorMessage);
13808 raise_application_error(errorCode,
13809 errorMessage);
13810 when badStatusException then
13811 ame_engine.unlockTransaction(fndApplicationIdIn => applicationIdIn,
13812 transactionIdIn => transactionIdIn,
13813 transactionTypeIdIn => transactionTypeIn);
13814 errorCode := -20001;
13815 if transactionTypeIn is not null then
13816 errorMessage := ame_util.getMessage(applicationShortNameIn => 'PER',
13817 messageNameIn => 'AME_400247_API_APPR_STAT_VALUE',
13818 tokenNameOneIn => 'TRANSACTION_ID',
13819 tokenValueOneIn => transactionIdIn,
13820 tokenNameTwoIn => 'TRANSACTION_TYPE',
13821 tokenValueTwoIn => transactionTypeIn,
13822 tokenNameThreeIn => 'APPROVED_STATUS',
13823 tokenValueThreeIn => ame_util.approvedStatus,
13824 tokenNameFourIn => 'APPROVED_FORWARD_STATUS',
13825 tokenValueFourIn => ame_util.approveAndForwardStatus,
13826 tokenNameFiveIn => 'EXCEPTION_STATUS',
13827 tokenValueFiveIn => ame_util.exceptionStatus ,
13828 tokenNameSixIn => 'FORWARD_STATUS',
13829 tokenValueSixIn => ame_util.forwardStatus,
13830 tokenNameSevenIn => 'REJECT_STATUS',
13831 tokenValueSevenIn => ame_util.rejectStatus);
13832 else
13833 errorMessage := ame_util.getMessage(applicationShortNameIn => 'PER',
13834 messageNameIn => 'AME_400064_API_APPR_STAT_VAL2',
13835 tokenNameOneIn => 'TRANSACTION_ID',
13836 tokenValueOneIn => transactionIdIn,
13837 tokenNameTwoIn => 'APPROVED_STATUS',
13838 tokenValueTwoIn => ame_util.approvedStatus,
13839 tokenNameThreeIn => 'APPROVED_FORWARD_STATUS',
13840 tokenValueThreeIn => ame_util.approveAndForwardStatus,
13841 tokenNameFourIn => 'EXCEPTION_STATUS',
13842 tokenValueFourIn => ame_util.exceptionStatus ,
13843 tokenNameFiveIn => 'FORWARD_STATUS',
13844 tokenValueFiveIn => ame_util.forwardStatus,
13845 tokenNameSixIn => 'REJECT_STATUS',
13846 tokenValueSixIn => ame_util.rejectStatus);
13847 end if;
13848 ame_util.runtimeException(packageNameIn => 'ame_engine',
13849 routineNameIn => 'updateApprovalStatus',
13850 exceptionNumberIn => errorCode,
13851 exceptionStringIn => errorMessage);
13852 raise_application_error(errorCode,
13853 errorMessage);
13854 when others then
13855 ame_engine.unlockTransaction(fndApplicationIdIn => applicationIdIn,
13856 transactionIdIn => transactionIdIn,
13857 transactionTypeIdIn => transactionTypeIn);
13858 ame_util.runtimeException(packageNameIn => 'ame_engine',
13859 routineNameIn => 'updateApprovalStatus',
13860 exceptionNumberIn => sqlcode,
13861 exceptionStringIn => sqlerrm);
13862 raise;
13863 end updateApprovalStatus;
13864 procedure updateInsertions(indexIn in integer) as
13865 tempIndex integer;
13866 approverInsertionOrder integer;
13867 deletionInsertionOrder integer;
13868 begin
13869 if engStInsertionIndexes.exists(indexIn) then
13870 deletionInsertionOrder := engStInsertionIndexes(indexIn);
13871 tempIndex := engStInsertionIndexes.next(indexIn);
13872 while engStInsertionIndexes.exists(tempIndex) loop
13873 approverInsertionOrder := engStInsertionIndexes(tempIndex);
13874 if approverInsertionOrder > deletionInsertionOrder then
13875 update ame_temp_insertions
13876 set parameter = parameter - 1
13877 where insertion_order = approverInsertionOrder
13878 and application_id = engAmeApplicationId
13879 and transaction_id = engTransactionId
13880 and order_type = ame_util.absoluteOrder;
13881 end if;
13882 tempIndex := engStInsertionIndexes.next(tempIndex);
13883 end loop;
13884 end if;
13885 end updateInsertions;
13886 procedure setDeviationReasonDate(reasonIn in varchar2,dateIn in date) as
13887 begin
13888 engTempReason := reasonIn;
13889 engTempDate := dateIn;
13890 end setDeviationReasonDate;
13891 end ame_engine;