DBA Data[Home] [Help]

PACKAGE BODY: APPS.AME_DUAL_CHAINS_HANDLER

Source


1 package body ame_dual_chains_handler as
2 /* $Header: ameedcha.pkb 120.6 2011/05/18 11:29:15 nchinnam ship $ */
3   /* package variables */
4   approverCategoriesDual ame_util.charList;
5   approverCategories ame_util.charList;
6   parametersCount integer;
7   parameterNumbers ame_util.idList;
8   parameters ame_util.stringList;
9   parameterSigns ame_util.charList;
10   ruleIds ame_util.idList;
11   ruleIdsDual ame_util.idList;
12   ruleSatisfiedYN ame_util.charList;
13   threshholdJobLevel integer;
14   topDogFound boolean;
15   topDogPersonId integer;
16   /* forward declarations */
17   /*
18     getCatSourceAndAuthority does not account for the ALLOW_REQUESTOR_APPROVAL attribute.
19     The handler procedure does that.
20   */
21   procedure getCatSourceAndAuthority(personIdIn in integer,
22                                      jobLevelIn in integer,
23                                      supervisorIdIn in integer,
24                                      categoryOut out nocopy varchar2,
25                                      sourceOut out nocopy varchar2,
26                                      hasFinalAuthorityYNOut out nocopy varchar2,
27                                      supervisorJobLevelOut out nocopy integer,
28                                      nextSupervisorIdOut out nocopy integer);
29   /*
30     parseAndSortRules populates the parameterNumbers and parameterSigns tables in
31     ascending lexicographic order, first by numerical order, then with '+' dominating '-'.
32     Note that it does not sort the parameters proper.
33   */
34   procedure parseAndSortRules(chainNumIn in integer);
35   /* procedures */
36   procedure getCatSourceAndAuthority(personIdIn in integer,
37                                      jobLevelIn in integer,
38                                      supervisorIdIn in integer,
39                                      categoryOut out nocopy varchar2,
40                                      sourceOut out nocopy varchar2,
41                                      hasFinalAuthorityYNOut out nocopy varchar2,
42                                      supervisorJobLevelOut out nocopy integer,
43                                      nextSupervisorIdOut out nocopy integer) as
44     category ame_util.charType;
45     errorCode integer;
46     errorMessage ame_util.longestStringType;
47     hasFinalAuthorityYN ame_util.charType;
48     noSupervisorException exception;
49     personDisplayName ame_util.longStringType;
50     source ame_util.longStringType;
51     supervisorJobLevel integer;
52     tempRuleRequiresApprover boolean;
53     tempRuleSatisfied boolean;
54     begin
55       /* Initialize the two output arguments that might not otherwise get set. */
56      supervisorJobLevelOut := null;
57      nextSupervisorIdOut := null;
58       /*
59         1.  An approver satisfies a rule in any of three cases:
60             A.  The rule's parameter number does not exceed the approver's job level.
61             B.  The rule's parameter sign is '-', and the job level of the approver's
62                 supervisor exceeds the rule's parameter number.
63             C.  The approver is the top dog.
64         2.  An approver has final authority if the approver satisfies all the rules.
65             (The handler procedure proper takes care of adding subsequent approvers at
66             the same job level, if the relevant mandatory attribute so requires.)
67         3.  The source value is a comma-delimited list of the IDs of the rules that
68             require an approver.  This procedure builds up the source value according
69             to the following logic:
70             A.  If a rule has not yet been satisfied, the rule requires the input
71                 approver.
72             B.  Otherwise, the rule requires the input approver only if the approver
73                 does <<not>> satisfy the rule.  (This would happen in the perverse case
74                 that an approver satisfies a rule, but their supervisor has a lower
75                 job level that does not satisfy the rule.)
76         4.  An approver's category is ame_util.approvalApproverCategory if any of the
77             rule usages requiring the approver is of that category; otherwise the
78             approver's category is ame_util.fyiApproverCategory.
79       */
80       category := ame_util.fyiApproverCategory;
81       hasFinalAuthorityYN := ame_util.booleanTrue;
82       for i in 1 .. parameterNumbers.count loop
83         /* Determine whether the approver satisfies the current rule. */
84         if(personIdIn = topDogPersonId) then
85           topDogFound := true;
86           tempRuleSatisfied := true;
87         else
88           topDogFound := false;
89           tempRuleSatisfied := false;
90           if(jobLevelIn >= parameterNumbers(i)) then
91             tempRuleSatisfied := true;
92           elsif(parameterSigns(i) = '-') then
93             if supervisorIdIn is null then
94               supervisorJobLevel := 0;
95             else
96               if(supervisorJobLevel is null) then
97                 if(supervisorIdIn is null) then
98                   raise noSupervisorException;
99                 end if;
100                 ame_absolute_job_level_handler.getJobLevelAndSupervisor(personIdIn => supervisorIdIn,
101                                        jobLevelOut => supervisorJobLevel,
102                                        supervisorIdOut => nextSupervisorIdOut);
103                 supervisorJobLevelOut := supervisorJobLevel;
104               end if;
105               if(supervisorJobLevel > parameterNumbers(i)) then
106                 tempRuleSatisfied := true;
107               end if;
108             end if;
109           end if;
110         end if;
111         /* Update hasFinalAuthorityYN as needed. */
112         if(not tempRuleSatisfied and
113            hasFinalAuthorityYN = ame_util.booleanTrue) then
114           hasFinalAuthorityYN := ame_util.booleanFalse;
115         end if;
116         /* Determine whether the current rule requires the approver. */
117         tempRuleRequiresApprover := false;
118         if(ruleSatisfiedYN(i) = ame_util.booleanTrue) then
119           if(not tempRuleSatisfied) then
120             tempRuleRequiresApprover := true;
121           end if;
122         else
123           tempRuleRequiresApprover := true;
124           if(tempRuleSatisfied) then
125             ruleSatisfiedYN(i) := ame_util.booleanTrue;
126           end if;
127         end if;
128         if(tempRuleRequiresApprover) then
129           /* Update source. */
130           ame_util.appendRuleIdToSource(ruleIdIn => ruleIds(i),
131                                         sourceInOut => source);
132           /* Update category as needed. */
133           if(category = ame_util.fyiApproverCategory and
134              approverCategories(i) = ame_util.approvalApproverCategory) then
135             category := ame_util.approvalApproverCategory;
136           end if;
137         end if;
138       end loop;
139       categoryOut := category;
140       hasFinalAuthorityYNOut := hasFinalAuthorityYN;
141       sourceOut := source;
142       exception
143         when noSupervisorException then
144           personDisplayName := ame_approver_type_pkg.getApproverDisplayName2(
145                                       origSystemIn => ame_util.perOrigSystem,
146                                       origSystemIdIn => personIdIn );
147           errorCode := -20205;
148           errorMessage := ame_util.getMessage(applicationShortNameIn => 'PER',
149             messageNameIn     => 'AME_400297_HAN_LACK_SPVR',
150             tokenNameOneIn    => 'FIRST_NAME',
151             tokenValueOneIn   => personDisplayName,
152             tokenNameTwoIn    => 'LAST_NAME',
153             tokenValueTwoIn   => null ,
154             tokenNameThreeIn  => 'OTHER_NAME',
155             tokenValueThreeIn =>  null );
156           ame_util.runtimeException(packageNameIn => 'ame_dual_chains_handler',
157                                     routineNameIn => 'getCatSourceAndAuthority',
158                                     exceptionNumberIn => errorCode,
159                                     exceptionStringIn => errorMessage);
160           raise_application_error(errorCode,
161                                   errorMessage);
162         when others then
163           categoryOut := null;
164           hasFinalAuthorityYNOut := null;
165           sourceOut := null;
166           ame_util.runtimeException(packageNameIn => 'ame_dual_chains_handler',
167                                     routineNameIn => 'getCatSourceAndAuthority',
168                                     exceptionNumberIn => sqlcode,
169                                     exceptionStringIn => sqlerrm);
170           raise;
171     end getCatSourceAndAuthority;
172   procedure handler as
173     chainOrderMode ame_util.stringType;
174     COAInsertee ame_util.approverRecord2;
175     errorCode integer;
176     errorMessage ame_util.longestStringType;
177     finalAuthorityApproverCategory ame_util.charType;
178     finalAuthorityFound boolean;
179     finalAuthoritySource ame_util.longStringType;
180     firstApproverSource ame_util.longStringType;
181     includeAllJobLevelApprovers boolean;
182     noSupervisorException exception;
183     nullFirstIdException exception;
184     nullSecondIdException exception;
185     firstStartingPointId integer;
186     oneChainException exception;
187     personDisplayName ame_util.longStringType;
188     secondStartingPointId integer;
189     tempApprover ame_util.approverRecord2;
190     tempHasFinalAuthorityYN ame_util.charType;
191     tempJobLevel integer;
192     tempMemberOrderNumber integer;
193     tempOldJobLevel integer;
194     tempSupervisorId integer;
195     tempSupervisorJobLevel integer;
196     tempNextSupervisorId integer;
197     votingRegimeType ame_util.stringType;
198     firstAuthInsExists boolean := false;
199     coaInsAuthForward boolean := false;
200     l_error_code number;
201     begin
202       includeAllJobLevelApprovers :=
203         ame_engine.getHeaderAttValue2(attributeNameIn => ame_util.includeAllApproversAttribute) =
204         ame_util.booleanAttributeTrue;
205       /* Populate some of the package variables. */
206       topDogPersonId := to_number(ame_engine.getHeaderAttValue2(attributeNameIn => ame_util.topSupPersonIdAttribute));
207       /* Set the fields in tempApprover that are constant for the entire handler cycle. */
208       tempApprover.orig_system := ame_util.perOrigSystem;
209       tempApprover.authority := ame_util.authorityApprover;
210       tempApprover.action_type_id := ame_engine.getHandlerActionTypeId;
211       tempApprover.item_class := ame_engine.getHandlerItemClassName;
212       tempApprover.item_id := ame_engine.getHandlerItemId;
213       tempApprover.item_class_order_number := ame_engine.getHandlerItemClassOrderNumber;
214       tempApprover.item_order_number := ame_engine.getHandlerItemOrderNumber;
215       tempApprover.sub_list_order_number := ame_engine.getHandlerSublistOrderNum;
216       tempApprover.action_type_order_number := ame_engine.getHandlerActionTypeOrderNum;
217       votingRegimeType := ame_engine.getActionTypeVotingRegime(actionTypeIdIn => tempApprover.action_type_id);
218       chainOrderMode := ame_engine.getActionTypeChainOrderMode(actionTypeIdIn => tempApprover.action_type_id);
219       /*
220         The engine only calls a handler if a rule requiring it exists, so we can assume that
221         the package variables that ame_engine.getHandlerRules initializes are nonempty.
222         Fetch the rules and sort them in increasing parameter order.  (Duplicate parameters
223         are harmless here.)
224       */
225       ame_engine.getHandlerRules2(ruleIdsOut => ruleIdsDual,
226                                   approverCategoriesOut => approverCategoriesDual,
227                                   parametersOut => parameters);
228       parametersCount := parameters.count;
229       for chainCounter in 1..2 loop
230         errorCode := -20238;
231         firstAuthInsExists := false;
232         coaInsAuthForward := false;
233         finalAuthorityApproverCategory := null;
234         finalAuthoritySource := null;
235         /* Check for COA 'firstAuthority' insertions */
236         ame_engine.getHandlerCOAFirstApprover(itemClassIn => tempApprover.item_class,
237                                               itemIdIn => tempApprover.item_id,
238                                               actionTypeIdIn =>tempApprover.action_type_id,
239                                               groupOrChainIdIn => chainCounter,
240                                               nameOut => COAInsertee.name,
241                                               origSystemOut => COAInsertee.orig_system,
242                                               origSystemIdOut =>COAInsertee.orig_system_id,
243                                               displayNameOut => COAInsertee.display_name,
244                                               sourceOut => COAInsertee.source);
245         if COAInsertee.name is  null then
246           if chainCounter = 1 then
247             /* Fetch the required attributes. */
248             firstStartingPointId :=
249               to_number(ame_engine.getHeaderAttValue2(attributeNameIn =>
250                                           ame_util.firstStartingPointAttribute));
251             if(firstStartingPointId is null ) then
252               raise nullFirstIdException;
253             end if;
254             tempApprover.orig_system_id := firstStartingPointId;
255           else  /* Chain is 2*/
256             /* Fetch the required attributes. */
257             secondStartingPointId :=
258               to_number(ame_engine.getHeaderAttValue2(attributeNameIn =>
259                                           ame_util.secondStartingPointAttribute));
260             if( secondStartingPointId is null) then
261               raise nullSecondIdException;
262             end if;
263             tempApprover.orig_system_id :=secondStartingPointId ;
264           end if;
265           tempApprover.api_insertion := ame_util.oamGenerated;
266           ame_approver_type_pkg.getWfRolesNameAndDisplayName(
267                               origSystemIn => ame_util.perOrigSystem,
268                               origSystemIdIn => tempApprover.orig_system_id,
269                               nameOut => tempApprover.name,
270                               displayNameOut => tempApprover.display_name);
271         else
272           tempApprover.name := COAInsertee.name;
273           tempApprover.orig_system := COAInsertee.orig_system;
274           tempApprover.orig_system_id := COAInsertee.orig_system_id;
275           tempApprover.display_name :=  COAInsertee.display_name;
276           firstApproverSource := COAInsertee.source;
277           tempApprover.api_insertion := ame_util.apiAuthorityInsertion;
278           firstAuthInsExists := true;
279         end if;
280         /* Get the threshholdJobLevel to convert parameters to absolute values */
281         ame_absolute_job_level_handler.getJobLevelAndSupervisor(
282                                  personIdIn => tempApprover.orig_system_id,
283                                  jobLevelOut => threshholdJobLevel,
284                                  supervisorIdOut => tempSupervisorId);
285         parseAndSortRules(chainNumIn => chainCounter);
286         tempJobLevel := threshholdJobLevel;
287         /* Check if there are any parameters defined for this chain. */
288         if parameterNumbers.count = 0 then
289           raise oneChainException;
290         end if;
291         for i in 1 .. parameterNumbers.count loop
292           ruleSatisfiedYN(i) := ame_util.booleanFalse;
293         end loop;
294         tempApprover.group_or_chain_id := chainCounter;
295         if (chainOrderMode = ame_util.serialChainsMode) then
296             tempApprover.group_or_chain_order_number := chainCounter;
297         else /* chain Order Mode is parallel */
298             tempApprover.group_or_chain_order_number := 1;
299         end if;
300         /* In this case self approval can not be done so build the chain. */
301         errorCode := -20239;
302         finalAuthorityFound := false;
303         tempMemberOrderNumber := 0; /* pre-increment */
304         loop
305           getCatSourceAndAuthority(personIdIn => tempApprover.orig_system_id,
306                                    jobLevelIn => tempJobLevel,
307                                    supervisorIdIn => tempSupervisorId,
308                                    categoryOut => tempApprover.approver_category,
309                                    sourceOut => tempApprover.source,
310                                    hasFinalAuthorityYNOut => tempHasFinalAuthorityYN,
311                                    supervisorJobLevelOut => tempSupervisorJobLevel,
312                                    nextSupervisorIdOut => tempNextSupervisorId);
313           /* reassign the value of source in case approver was a firstAuthority insertee */
314           if firstApproverSource is not null then
315             tempApprover.source := firstApproverSource;
316             firstApproverSource := null;
317           end if;
318           if(not finalAuthorityFound and
319              tempHasFinalAuthorityYN = ame_util.booleanTrue) then
320             finalAuthorityFound := true;
321             finalAuthorityApproverCategory := tempApprover.approver_category;
322             finalAuthoritySource := tempApprover.source;
323           end if;
324           if (tempApprover.source is null and
325              finalAuthoritySource is not null ) then
326             tempApprover.approver_category := finalAuthorityApproverCategory;
327             tempApprover.source := finalAuthoritySource;
328           end if;
329           tempApprover.occurrence := ame_engine.getHandlerOccurrence(nameIn=>tempApprover.name,
330                                                   itemClassIn => tempApprover.item_class,
331                                                   itemIdIn => tempApprover.item_id,
332                                                   actionTypeIdIn => tempApprover.action_type_id,
333                                                   groupOrChainIdIn => tempApprover.group_or_chain_id);
334 
335           tempMemberOrderNumber := tempMemberOrderNumber + 1;
336           if(votingRegimeType = ame_util.serializedVoting) then
337             tempApprover.member_order_number := tempMemberOrderNumber;
338           else /* votingRegimeType in (ame_util.consensusVoting, ame_util.firstApproverVoting) */
339             tempApprover.member_order_number := 1;
340           end if;
341           tempApprover.approval_status := ame_engine.getHandlerApprovalStatus(approverIn => tempApprover);
342           /* The engine will set tempApprover.approver_order_number; leave it null here. */
343           ame_engine.addApprover(approverIn => tempApprover);
344           /* check to see if there is a COA insertion after this approver. If a COA
345              insertion is found, keep checking till no more COA insertions. The check
346              for final authority will need to be done again.  */
347           loop
348             /* Initialize COAInsertee approverRecord2 */
349             COAInsertee := ame_util.emptyApproverRecord2;
350             /* Check if there are any COAInsertions */
351             ame_engine.getHandlerCOAInsertion(nameIn => tempApprover.name,
352                                             itemClassIn => tempApprover.item_class,
353                                             itemIdIn => tempApprover.item_id,
354                                             actionTypeIdIn => tempApprover.action_type_id,
355                                             groupOrChainIdIn => tempApprover.group_or_chain_id,
356                                             occurrenceIn => tempApprover.occurrence,
357                                             approvalStatusIn => tempApprover.approval_status,
358                                             nameOut => COAInsertee.name,
359                                             origSystemOut => COAInsertee.orig_system,
360                                             origSystemIdOut => COAInsertee.orig_system_id,
361                                             displayNameOut => COAInsertee.display_name,
362                                             sourceOut => COAInsertee.source);
363             if COAInsertee.name is null then
364               exit;
365             else
366               tempApprover.name := COAInsertee.name;
367               tempApprover.orig_system := COAInsertee.orig_system;
368               tempApprover.orig_system_id := COAInsertee.orig_system_id;
369               tempApprover.display_name :=  COAInsertee.display_name;
370               ame_absolute_job_level_handler.getJobLevelAndSupervisor(
371                                        personIdIn => tempApprover.orig_system_id,
372                                        jobLevelOut => tempJobLevel,
373                                        supervisorIdOut => tempSupervisorId);
374               getCatSourceAndAuthority(personIdIn => tempApprover.orig_system_id,
375                                        jobLevelIn => tempJobLevel,
376                                        supervisorIdIn => tempSupervisorId,
377                                        categoryOut => tempApprover.approver_category,
378                                        sourceOut => tempApprover.source,
379                                        hasFinalAuthorityYNOut => tempHasFinalAuthorityYN,
380                                        supervisorJobLevelOut => tempSupervisorJobLevel,
381                                        nextSupervisorIdOut => tempNextSupervisorId);
382               tempApprover.source := COAInsertee.source;
383               tempApprover.approver_category := ame_util.approvalApproverCategory;
384               tempApprover.api_insertion := ame_util.apiAuthorityInsertion;
385               tempMemberOrderNumber := tempMemberOrderNumber + 1;
386               if(votingRegimeType = ame_util.serializedVoting) then
387                 tempApprover.member_order_number := tempMemberOrderNumber;
388               else /* votingRegimeType in (ame_util.consensusVoting, ame_util.firstApproverVoting) */
389                 tempApprover.member_order_number := 1;
390               end if;
391               tempApprover.occurrence := ame_engine.getHandlerOccurrence(nameIn =>  tempApprover.name,
392                                               itemClassIn => tempApprover.item_class,
393                                               itemIdIn => tempApprover.item_id,
394                                               actionTypeIdIn => tempApprover.action_type_id,
395                                               groupOrChainIdIn => tempApprover.group_or_chain_id);
396               tempApprover.approval_status := ame_engine.getHandlerApprovalStatus(approverIn => tempApprover);
397               /* If approver has a status of ame_util.approve or ame_util.approveAndForwardStatus or
398                  ame_util.nullStatus check to see if approver could have final authority */
399               if ((tempApprover.approval_status is null) or
400                 (tempApprover.approval_status in
401                         (ame_util.approvedStatus, ame_util.approveAndForwardStatus,
402                          ame_util.repeatedStatus, ame_util.suppressedStatus,
403                          ame_util.beatByFirstResponderStatus, ame_util.nullStatus)) or
404                 (tempApprover.approver_category = ame_util.approvalApproverCategory and
405                  tempApprover.approval_status = ame_util.notifiedStatus) )
406                 then
407                 if(not finalAuthorityFound and
408                   tempHasFinalAuthorityYN = ame_util.booleanTrue) then
409                   finalAuthorityFound := true;
410                 end if;
411               end if;
412               ame_engine.addApprover(approverIn => tempApprover);
413               coaInsAuthForward := true;
414             end if;
415           end loop;
416           /* Decide whether to end the chain. */
417           if(topDogFound or
418              (finalAuthorityFound and
419              not includeAllJobLevelApprovers)) then
420             exit;
421           end if;
422           /* Check to make sure tempSupervisorId is not null, else raise noSupervisorException */
423           if tempSupervisorId is null then
424             raise noSupervisorException;
425           else
426             tempApprover.orig_system_id := tempSupervisorId;
427           end if;
428           tempOldJobLevel := tempJobLevel;
429           if(tempSupervisorJobLevel is null) then
430             ame_absolute_job_level_handler.getJobLevelAndSupervisor(personIdIn => tempApprover.orig_system_id,
431                                    jobLevelOut => tempJobLevel,
432                                    supervisorIdOut => tempSupervisorId);
433           else
434             tempJobLevel := tempSupervisorJobLevel;
435             tempSupervisorId := tempNextSupervisorId;
436           end if;
437           /*
438           At this point finalAuthorityFound implies includeAllJobLevelApprovers, so the following if
439           doesn't need to check includeAllJobLevelApprovers.  But it's implicit in the if statement.
440           */
441           if(finalAuthorityFound and
442              tempOldJobLevel <> tempJobLevel) then
443             exit;
444           end if;
445           tempApprover.api_insertion := ame_util.oamGenerated;
446           ame_approver_type_pkg.getWfRolesNameAndDisplayName(
447                                     origSystemIn => ame_util.perOrigSystem,
448                                     origSystemIdIn => tempApprover.orig_system_id,
449                                     nameOut => tempApprover.name,
450                                     displayNameOut => tempApprover.display_name);
451           if firstAuthInsExists then
452             ame_engine.setDeviationReasonDate(ame_approver_deviation_pkg.firstauthHandlerInsReason,null);
453           end if;
454           if coaInsAuthForward then
455             ame_engine.setDeviationReasonDate(ame_approver_deviation_pkg.forwarHandlerAuthInsReason,null);
456           end if;
457         end loop;
458       end loop;
459       exception
460         when oneChainException then
461           errorCode := -20001;
462           errorMessage := ame_util.getMessage(applicationShortNameIn => 'PER',
463                                               messageNameIn => 'AME_400253_HAN_ONE_CHN_REQ');
464           ame_util.runtimeException(packageNameIn => 'ame_dual_chains_handler',
465                                     routineNameIn => 'handler',
466                                     exceptionNumberIn => errorCode,
467                                     exceptionStringIn => errorMessage);
468           raise_application_error(errorCode,
469                                   errorMessage);
470         when noSupervisorException then
471           if tempApprover.display_name is null then
472             personDisplayName := ame_approver_type_pkg.getApproverDisplayName2(
473                                       origSystemIn => ame_util.perOrigSystem,
474                                       origSystemIdIn => tempApprover.orig_system_id );
475           else
476             personDisplayName := tempApprover.display_name;
477           end if;
478           errorCode := -20205;
479           errorMessage := ame_util.getMessage(applicationShortNameIn => 'PER',
480             messageNameIn     => 'AME_400297_HAN_LACK_SPVR',
481             tokenNameOneIn    => 'FIRST_NAME',
482             tokenValueOneIn   => personDisplayName,
483             tokenNameTwoIn    => 'LAST_NAME',
484             tokenValueTwoIn   => null ,
485             tokenNameThreeIn  => 'OTHER_NAME',
486             tokenValueThreeIn =>  null );
487           ame_util.runtimeException(packageNameIn => 'ame_dual_chains_handler',
488                                     routineNameIn => 'handler',
489                                     exceptionNumberIn => errorCode,
490                                     exceptionStringIn => errorMessage);
491           raise_application_error(errorCode,
492                                   errorMessage);
493         when nullFirstIdException then
494           errorCode := -20001;
495           errorMessage :=
496           ame_util.getMessage(applicationShortNameIn => 'PER',
497                               messageNameIn   => 'AME_400250_HAN_NULL_FRST_STRT',
498                               tokenNameOneIn  => 'STARTING_POINT_ATTRIBUTE',
499                               tokenValueOneIn => ame_util.firstStartingPointAttribute);
500           ame_util.runtimeException(packageNameIn => 'ame_dual_chains_handler',
501                                     routineNameIn => 'handler',
502                                     exceptionNumberIn => errorCode,
503                                     exceptionStringIn => errorMessage);
504           raise_application_error(errorCode,
505                                   errorMessage);
506         when nullSecondIdException then
507           errorCode := -20001;
508           errorMessage :=
509           ame_util.getMessage(applicationShortNameIn => 'PER',
510                               messageNameIn   => 'AME_400250_HAN_NULL_FRST_STRT',
511                               tokenNameOneIn  => 'STARTING_POINT_ATTRIBUTE',
512                               tokenValueOneIn => ame_util.secondStartingPointAttribute);
513           ame_util.runtimeException(packageNameIn => 'ame_dual_chains_handler',
514                                     routineNameIn => 'handler',
515                                     exceptionNumberIn => errorCode,
516                                     exceptionStringIn => errorMessage);
517           raise_application_error(errorCode,
518                                   errorMessage);
519         when others then
520           ame_util.runtimeException(packageNameIn => 'ame_dual_chains_handler',
521                                     routineNameIn => 'handler',
522                                     exceptionNumberIn => sqlcode,
523                                     exceptionStringIn => sqlerrm);
524           l_error_code := sqlcode;
525           if l_error_code = -20213 then
526             errorMessage := ame_util.getMessage(applicationShortNameIn =>'PER',
527                                               messageNameIn => 'AME_400834_INV_HANDLR_APR',
528                                               tokenNameOneIn  => 'ACTION_TYPE_NAME',
529                                               tokenValueOneIn => ame_engine.getActionTypeName(tempApprover.action_type_id),
530                                               tokenNameTwoIn => 'ORIG_SYSTEM',
531                                               tokenValueTwoIn => ame_util.perOrigSystem,
532                                               tokenNameThreeIn => 'ORIG_SYSEM_ID',
533                                               tokenValueThreeIn => tempApprover.orig_system_id);
534            raise_application_error(errorCode,errorMessage);
535           end if;
536           raise;
537     end handler;
538   procedure parseAndSortRules(chainNumIn in integer)  as
539     badParameterException exception;
540     errorCode integer;
541     errorMessage ame_util.longestStringType;
542     tempCategory ame_util.charType;
543     tempIndex integer;
544     tempLength integer;
545     tempNumber integer;
546     tempRuleId integer;
547     tempSign ame_util.charType;
548     upperLimit integer;
549     begin
550       /* Parse. */
551       tempIndex := 0;
552       parameterNumbers.delete;
553       parameterSigns.delete;
554       approverCategories.delete;
555       ruleIds.delete;
556       for i in 1 .. parametersCount  loop
557         if (chainNumIn = 1 and
558            (substrb(parameters(i), 1, 1) = '1')) then
559           tempIndex := tempIndex + 1;
560           tempLength := lengthb(parameters(i));
561           if substrb(parameters(i), 2, 1) = 'R' then
562             parameterNumbers(tempIndex) := threshholdJobLevel +
563                         to_number(substrb(parameters(i), 3, tempLength - 3));
564             parameterSigns(tempIndex) := substrb(parameters(i), -1, 1);
565           else
566             parameterNumbers(tempIndex) := to_number(substrb(parameters(i),3,tempLength- 3));
567             parameterSigns(tempIndex) := substrb(parameters(i), -1, 1);
568           end if;
569           approverCategories(tempIndex) := approverCategoriesDual(i);
570           ruleIds(tempIndex) := ruleIdsDual(i);
571           if(parameterSigns(tempIndex) <> '+' and
572              parameterSigns(tempIndex) <> '-') then
573             raise badParameterException;
574           end if;
575         elsif (chainNumIn = 2 and
576            (substrb(parameters(i), 1, 1) = '2')) then
577           tempIndex := tempIndex + 1;
578           tempLength := lengthb(parameters(i));
579           if substrb(parameters(i), 2, 1) = 'R' then
580             parameterNumbers(tempIndex) := threshholdJobLevel +
581                         to_number(substrb(parameters(i), 3, tempLength - 3));
582             parameterSigns(tempIndex) := substrb(parameters(i), -1, 1);
583           else
584             parameterNumbers(tempIndex) := to_number(substrb(parameters(i),3,tempLength- 3));
585             parameterSigns(tempIndex) := substrb(parameters(i), -1, 1);
586           end if;
587           approverCategories(tempIndex) := approverCategoriesDual(i);
588           ruleIds(tempIndex) := ruleIdsDual(i);
589           if(parameterSigns(tempIndex) <> '+' and
590              parameterSigns(tempIndex) <> '-') then
591             raise badParameterException;
592           end if;
593         end if;
594       end loop;
595       /* Sort. */
596       for i in 2 .. tempIndex loop
597         upperLimit := i - 1;
598         for j in 1 .. upperLimit loop
599           if(parameterNumbers(i) < parameterNumbers(j) or
600              (parameterNumbers(i) = parameterNumbers(j) and
601               parameterSigns(i) = '-' and parameterSigns(j) = '+')) then
602             tempRuleId := ruleIds(j);
603             tempCategory := approverCategories(j);
604             tempNumber := parameterNumbers(j);
605             tempSign := parameterSigns(j);
606             ruleIds(j) := ruleIds(i);
607             approverCategories(j) := approverCategories(i);
608             parameterNumbers(j) := parameterNumbers(i);
609             parameterSigns(j) := parameterSigns(i);
610             ruleIds(i) := tempRuleId;
611             approverCategories(i) := tempCategory;
612             parameterNumbers(i) := tempNumber;
613             parameterSigns(i) := tempSign;
614           end if;
615         end loop;
616       end loop;
617       exception
618         when badParameterException then
619           errorCode := -20001;
620           errorMessage := ame_util.getMessage(applicationShortNameIn => 'PER',
621                                               messageNameIn => 'AME_400234_HAN_ACT_PAR_SIGN');
622           ame_util.runtimeException(packageNameIn => 'ame_dual_chains_handler',
623                                     routineNameIn => 'parseAndSortRules',
624                                     exceptionNumberIn => errorCode,
625                                     exceptionStringIn => errorMessage);
626           raise_application_error(errorCode,
627                                   errorMessage);
628         when others then
629           ame_util.runtimeException(packageNameIn => 'ame_dual_chains_handler',
630                                     routineNameIn => 'parseAndSortRules',
631                                     exceptionNumberIn => sqlcode,
632                                     exceptionStringIn => sqlerrm);
633           raise;
634     end parseAndSortRules;
635 end ame_dual_chains_handler;