[Home] [Help]
PACKAGE BODY: APPS.AME_AG_CHAIN_HANDLER
Source
1 package body ame_ag_chain_handler as
2 /* $Header: ameegcha.pkb 120.4 2007/12/12 12:47:27 prasashe noship $ */
3 /* package variables */
4 approverCategories ame_util.charList;
5 groupIds ame_util.idList;
6 groupOrderNumbers ame_util.idList;
7 ruleIds ame_util.idList;
8 parameters ame_util.stringList;
9 parameterTwos ame_util.stringList;
10 sources ame_util.longStringList;
11 votingRegimes ame_util.charList;
12 /* forward declarations */
13 procedure eliminateDuplicates;
14 /* Procedures */
15 procedure eliminateDuplicates as
16 begin
17 for i in 2 .. groupIds.count loop
18 if(groupIds(i) = groupIds(i - 1)) then
19 /*
20 Preserve the deleted rule's ID in the preserved rule's source field, if space permits.
21 In the very unlikely event otherwise, silently omit the extra source value(s). (The
22 alternative would be to raise an exception that would require for its solution either
23 a code change or a change to the structure of the rules or transaction--none of which
24 would please the end user.)
25 */
26 if(lengthb(sources(i - 1)) + lengthb(sources(i)) + 1 <= ame_util.longStringTypeLength) then
27 sources(i) := sources(i) || ame_util.fieldDelimiter || sources(i - 1);
28 end if;
29 /* Make sure the dominant approver category is preserved. */
30 if(approverCategories(i) <> ame_util.approvalApproverCategory and
31 approverCategories(i - 1) = ame_util.approvalApproverCategory) then
32 approverCategories(i) := ame_util.approvalApproverCategory;
33 end if;
34 /* Delete the duplicate group. */
35 approverCategories.delete(i - 1);
36 groupIds.delete(i - 1);
37 groupOrderNumbers.delete(i - 1);
38 ruleIds.delete(i - 1);
39 parameters.delete(i - 1);
40 parameterTwos.delete(i - 1);
41 sources.delete(i - 1);
42 votingRegimes.delete(i - 1);
43 end if;
44 end loop;
45 exception
46 when others then
47 ame_util.runtimeException(packageNameIn => 'ame_ag_chain_handler',
48 routineNameIn => 'eliminateDuplicates',
49 exceptionNumberIn => sqlcode,
50 exceptionStringIn => sqlerrm);
51 raise;
52 end eliminateDuplicates;
53 procedure handler as
54 chainOrderMode ame_util.stringType;
55 COAInsertee ame_util.approverRecord2;
56 errorCode integer;
57 errorMessage ame_util.longestStringType;
58 finalAuthorityFound boolean;
59 groupOrderNumber integer;
60 nullFirstIdException exception;
61 requestorId integer;
62 startingPointId integer;
63 tempApprover ame_util.approverRecord2;
64 tempApproverNames ame_util.longStringList;
65 tempApproverOrderNumbers ame_util.idList;
66 tempApproverDisplayNames ame_util.longStringList;
67 tempOrigSystemIds ame_util.idList;
68 tempOrigSystems ame_util.stringList;
69 tempHasFinalAuthorityYN ame_util.charType;
70 tempIndex integer;
71 tempMemberOrderNumber integer := 1;
72 tempSupervisorId integer;
73 votingRegimeType ame_util.stringType;
74 allowEmptyGroups boolean;
75 currentApproverGrpMemberCount integer;
76 currentApproverGroupId integer;
77 emptyGroupException exception;
78 begin
79 /*
80 The engine only calls a handler if a rule requiring it exists, so we can assume that
81 the package variables that ame_engine.getHandlerRules initializes are nonempty.
82 Fetch the rules and sort them in increasing parameter order. (Duplicate parameters
83 are harmless here.)
84 */
85 ame_engine.getHandlerRules(ruleIdsOut => ruleIds,
86 approverCategoriesOut => approverCategories,
87 parametersOut => parameters,
88 parameterTwosOut => parameterTwos);
89 /* Initialize the source list. */
90 for i in 1 .. ruleIds.count loop
91 sources(i) := to_char(ruleIds(i));
92 end loop;
93 /*
94 Convert the parameters to group IDs (integers), then fetch the groups' order numbers
95 and ordering modes.
96 */
97 ame_util.stringListToIdList(stringListIn => parameters,
98 idListOut => groupIds);
99 /* Bug:4491715 when get configs we sort group ids so corresponding sources and categories
100 must also be sorted */
101 ame_engine.getApprovalGroupConfigs(groupIdsInOut => groupIds,
102 sourcesInOut => sources,
103 approverCategoriesInOut => approverCategories,
104 orderNumbersOut => groupOrderNumbers,
105 votingRegimesOut => votingRegimes);
106 /* Eliminate duplicate group-ID entries, possibly leaving the package-variable lists sparse. */
107 eliminateDuplicates;
108 /* Find the transaction allows empty approval groups or not */
109 allowEmptyGroups :=
110 ame_engine.getHeaderAttValue2(attributeNameIn => ame_util.allowEmptyGroupAttribute)
111 = ame_util.booleanAttributeTrue;
112 /* Set the fields in tempApprover that are constant for the entire handler cycle. */
113 tempApprover.orig_system := ame_util.perOrigSystem;
114 tempApprover.authority := ame_util.authorityApprover;
115 tempApprover.action_type_id := ame_engine.getHandlerActionTypeId;
116 tempApprover.group_or_chain_id := groupIds(groupIds.first);
117 tempApprover.api_insertion := ame_util.oamGenerated;
118 tempApprover.item_class := ame_engine.getHandlerItemClassName;
119 tempApprover.item_id := ame_engine.getHandlerItemId;
120 tempApprover.item_class_order_number := ame_engine.getHandlerItemClassOrderNumber;
121 tempApprover.item_order_number := ame_engine.getHandlerItemOrderNumber;
122 tempApprover.sub_list_order_number := ame_engine.getHandlerSublistOrderNum;
123 tempApprover.action_type_order_number := ame_engine.getHandlerActionTypeOrderNum;
124 votingRegimeType := ame_engine.getActionTypeVotingRegime(actionTypeIdIn => tempApprover.action_type_id);
125 chainOrderMode := ame_engine.getActionTypeChainOrderMode(actionTypeIdIn => tempApprover.action_type_id);
126 /* Check for COA First Authority Insertion */
127 ame_engine.getHandlerCOAFirstApprover(itemClassIn => tempApprover.item_class,
128 itemIdIn => tempApprover.item_id,
129 actionTypeIdIn => tempApprover.action_type_id,
130 groupOrChainIdIn => tempApprover.group_or_chain_id,
131 nameOut => COAInsertee.name,
132 origSystemOut => COAInsertee.orig_system,
133 origSystemIdOut => COAInsertee.orig_system_id,
134 displayNameOut => COAInsertee.display_name,
135 sourceOut => COAInsertee.source);
136 /* If COA Insertee exists add as first approver and then continue normal processing */
137 if COAInsertee.name is null then
138 tempApprover.api_insertion := ame_util.oamGenerated;
139 /* Bug fix 4468908 */
140 groupOrderNumber := 1;
141 else
142 /* Bug fix 4468908 */
143 groupOrderNumber := 2;
144 tempApprover.name := COAInsertee.name;
145 tempApprover.orig_system := COAInsertee.orig_system;
146 tempApprover.orig_system_id := COAInsertee.orig_system_id;
147 tempApprover.display_name := COAInsertee.display_name;
148 tempApprover.source := COAInsertee.source;
149 tempApprover.api_insertion := ame_util.apiAuthorityInsertion;
150 tempApprover.approver_category := ame_util.approvalApproverCategory;
151 tempApprover.group_or_chain_id := groupIds(groupIds.first);
152 tempApprover.occurrence := ame_engine.getHandlerOccurrence(nameIn=>tempApprover.name,
153 itemClassIn => tempApprover.item_class,
154 itemIdIn => tempApprover.item_id,
155 actionTypeIdIn => tempApprover.action_type_id,
156 groupOrChainIdIn => tempApprover.group_or_chain_id);
157 tempApprover.group_or_chain_order_number := 1;
158 tempApprover.member_order_number := 1;
159 tempApprover.approval_status := ame_engine.getHandlerApprovalStatus(approverIn=>tempApprover);
160 /*
161 The engine will set tempApprover.approver_order_number; leave them null here.
162 */
163 ame_engine.addApprover(approverIn => tempApprover);
164 end if;
165 /*
166 Now iterate through the sorted groups, adding their membership to the engine's
167 approver list in the group-member order dictated by the group's voting regime
168 (and possibly its members' order numbers).
169 */
170 tempIndex := groupIds.first;
171 while(tempIndex is not null) loop
172 /* Clear the group-member buffers of any previous data. */
173 tempApproverNames.delete;
174 tempApproverOrderNumbers.delete;
175 tempApproverDisplayNames.delete;
176 tempOrigSystemIds.delete;
177 tempOrigSystems.delete;
178 /* Fetch the group's membership. */
179 ame_engine.getRuntimeGroupMembers(groupIdIn => groupIds(tempIndex),
180 approverNamesOut => tempApproverNames,
181 approverOrderNumbersOut => tempApproverOrderNumbers,
182 approverDisplayNamesOut => tempApproverDisplayNames,
183 origSystemIdsOut => tempOrigSystemIds,
184 origSystemsOut => tempOrigSystems);
185 currentApproverGrpMemberCount := tempApproverNames.count;
186 currentApproverGroupId := groupIds(tempIndex);
187 /* Throw error if the current group is empty and the transaction
188 doesnt accept empty groups */
189 if(not allowEmptyGroups and currentApproverGrpMemberCount = 0 ) then
190 raise emptyGroupException;
191 end if;
192 /* Add the group's members to the approver list. */
193 for j in 1 .. tempApproverNames.count loop
194 tempApprover.name := tempApproverNames(j);
195 tempApprover.orig_system := tempOrigSystems(j);
196 tempApprover.orig_system_id := tempOrigSystemIds(j);
197 tempApprover.display_name := tempApproverDisplayNames(j);
198 tempApprover.approver_category := approverCategories(tempIndex);
199 tempApprover.api_insertion := ame_util.oamGenerated;
200 tempApprover.group_or_chain_id := groupIds(tempIndex);
201 tempApprover.occurrence := ame_engine.getHandlerOccurrence(nameIn => tempApprover.name,
202 itemClassIn => tempApprover.item_class,
203 itemIdIn => tempApprover.item_id,
204 actionTypeIdIn => tempApprover.action_type_id,
205 groupOrChainIdIn => tempApprover.group_or_chain_id);
206 tempApprover.source := sources(tempIndex);
207 if (chainOrderMode = ame_util.serialChainsMode) then
208 tempApprover.group_or_chain_order_number := groupOrderNumber;
209 else /* chain Order Mode is parallel */
210 tempApprover.group_or_chain_order_number := 1;
211 end if;
212 if(votingRegimeType = ame_util.orderNumberVoting) then
213 tempApprover.member_order_number := tempApproverOrderNumbers(j);
214 elsif(votingRegimeType = ame_util.serializedVoting) then
215 tempApprover.member_order_number := tempMemberOrderNumber;
216 else /* votingRegimeType in (ame_util.consensusVoting, ame_util.firstApproverVoting) */
217 tempApprover.member_order_number := 1;
218 end if;
219 tempApprover.approval_status := ame_engine.getHandlerApprovalStatus(approverIn => tempApprover);
220 /*
221 The engine will set tempApprover.approver_order_number; leave them null here.
222 */
223 ame_engine.addApprover(approverIn => tempApprover);
224 /* Check if there is any COA Insertion after this approver. If a COA Insertee is
225 found keep checking till there are no more COA Insertee's */
226 loop
227 /* Initialize COAInsertee approver record 2 */
228 COAInsertee := ame_util.emptyApproverRecord2;
229 /* Check if there are any chain of authority insertions */
230 ame_engine.getHandlerCOAInsertion(nameIn => tempApprover.name,
231 itemClassIn => tempApprover.item_class,
232 itemIdIn => tempApprover.item_id,
233 actionTypeIdIn => tempApprover.action_type_id,
234 groupOrChainIdIn => tempApprover.group_or_chain_id,
235 occurrenceIn => tempApprover.occurrence,
236 approvalStatusIn => tempApprover.approval_status,
237 nameOut => COAInsertee.name,
238 origSystemOut => COAInsertee.orig_system,
239 origSystemIdOut => COAInsertee.orig_system_id,
240 displayNameOut => COAInsertee.display_name,
241 sourceOut => COAInsertee.source);
242 if COAInsertee.name is null then
243 exit;
244 else
245 tempApprover.name := COAInsertee.name;
246 tempApprover.orig_system := COAInsertee.orig_system;
247 tempApprover.orig_system_id := COAInsertee.orig_system_id;
248 tempApprover.display_name := COAInsertee.display_name;
249 tempApprover.source := COAInsertee.source;
250 tempApprover.approver_category := ame_util.approvalApproverCategory;
251 tempApprover.api_insertion := ame_util.apiAuthorityInsertion;
252 tempApprover.group_or_chain_id := groupIds(tempIndex);
253 tempApprover.occurrence := ame_engine.getHandlerOccurrence(
254 nameIn => tempApprover.name,
255 itemClassIn => tempApprover.item_class,
256 itemIdIn => tempApprover.item_id,
257 actionTypeIdIn => tempApprover.action_type_id,
258 groupOrChainIdIn => tempApprover.group_or_chain_id);
259 if (chainOrderMode = ame_util.serialChainsMode) then
260 tempApprover.group_or_chain_order_number := groupOrderNumber;
261 else /* chain Order Mode is parallel */
262 tempApprover.group_or_chain_order_number := 1;
263 end if;
264 if(votingRegimeType = ame_util.orderNumberVoting) then
265 tempApprover.member_order_number := tempApproverOrderNumbers(j);
266 elsif(votingRegimeType = ame_util.serializedVoting) then
267 tempMemberOrderNumber := tempMemberOrderNumber+1;
268 tempApprover.member_order_number := tempMemberOrderNumber;
269 else /* votingRegimeType in (ame_util.consensusVoting, ame_util.firstApproverVoting) */
270 tempApprover.member_order_number := 1;
271 end if;
272 tempApprover.approval_status := ame_engine.getHandlerApprovalStatus(approverIn => tempApprover);
273 /*
274 The engine will set tempApprover.approver_order_number; leave them null here.
275 */
276 ame_engine.addApprover(approverIn => tempApprover);
277 end if;
278 end loop;
279 if(votingRegimeType = ame_util.serializedVoting) then
280 tempMemberOrderNumber := tempMemberOrderNumber+1;
281 end if;
282 end loop;
283 tempIndex := groupIds.next(tempIndex);
284 groupOrderNumber := groupOrderNumber + 1;
285 end loop;
286 exception
287 when emptyGroupException then
288 errorCode := -20001;
289 errorMessage :=
290 ame_util.getMessage(applicationShortNameIn => 'PER',
291 messageNameIn => 'AME_400229_HAN_APR_NO_MEM',
292 tokenNameOneIn => 'APPROVAL_GROUP',
293 tokenValueOneIn => ame_approval_group_pkg.getName(approvalGroupIdIn => currentApproverGroupId));
294 ame_util.runtimeException(packageNameIn => 'ame_ag_chain_handler',
295 routineNameIn => 'handler',
296 exceptionNumberIn => errorCode,
297 exceptionStringIn => errorMessage);
298 raise_application_error(errorCode,
299 errorMessage);
300 when others then
301 ame_util.runtimeException(packageNameIn => 'ame_ag_chain_handler',
302 routineNameIn => 'handler',
303 exceptionNumberIn => sqlcode,
304 exceptionStringIn => sqlerrm);
305 raise;
306 end handler;
307 end ame_ag_chain_handler;