1 PACKAGE BODY AMW_RL_HIERARCHY_PKG AS
2 /*$Header: amwrlhrb.pls 120.6 2006/03/20 02:52:55 appldev noship $*/
3
4 function encode (n1 in number, n2 in number) return varchar2 is
5 begin
6 return to_char(n1) || ':' || to_char(n2);
7 end encode;
8
9 procedure init is
10 begin
11
12 x_index := 0;
13 x_process_tbl := process_tbl();
14 x_parent_child_tbl := parent_child_tbl();
15 x_up_down_ind_tbl := up_down_ind_tbl();
16
17 x_index_tbl.delete;
18 x_t1.delete;
19 x_t2.delete;
20
21 end init;
22
23
24 function is_ancestor_in_hierarchy(p_process1_id in number,
25 p_process2_id in number)
26 return boolean
27 is
28 cursor c_relation_exists (l_ancestor_id number,
29 l_descendant_id number) is
30 select 1 from amw_proc_hierarchy_denorm
31 where process_id = l_ancestor_id and
32 parent_child_id = l_descendant_id and
33 hierarchy_type = 'L' and
34 up_down_ind = 'D';
35 l_dummy number;
36 begin
37
38 open c_relation_exists(p_process1_id, p_process2_id);
39 fetch c_relation_exists into l_dummy;
40 if (c_relation_exists%found)
41 then
42 close c_relation_exists;
43 return true;
44 else
45 close c_relation_exists;
46 return false;
47 end if;
48
49
50 end is_ancestor_in_hierarchy;
51
52 procedure add_rows_to_denorm
53 (p_ancestor_id in number,
54 p_descendant_id in number)
55
56 is
57
58 begin
59 x_index := x_index+2;
60 x_process_tbl.extend(2);
61 x_parent_child_tbl.extend(2);
62 x_up_down_ind_tbl.extend(2);
63
64 --add the new relation
65 x_process_tbl(x_index-1) := p_ancestor_id;
66 x_parent_child_tbl(x_index-1) := p_descendant_id;
67 x_up_down_ind_tbl(x_index-1) := 'D';
68
69 --add the new relation
70 x_process_tbl(x_index) := p_descendant_id;
71 x_parent_child_tbl(x_index) := p_ancestor_id;
72 x_up_down_ind_tbl(x_index) := 'U';
73 x_index_tbl(encode(p_ancestor_id,p_descendant_id)) := 1;
74 end add_rows_to_denorm;
75
76
77 procedure update_denorm_add_child(p_parent_id number,
78 p_child_id number,
79 l_sysdate in Date default sysdate)
80
81 is
82
83 -- CURSOR TO SELECT ALL THE ANCESTORS OF THE GIVEN PROCESS.
84 cursor c_ancestors(l_process_id number) is
85 select parent_child_id
86 from amw_proc_hierarchy_denorm
87 where process_id = l_process_id and
88 up_down_ind = 'U';
89
90 type ancestor_tbl is table of c_ancestors%rowtype;
91
92
93 -- CURSOR TO SELECT ALL THE DESCENDANTS OF THE GIVEN PROCESS.
94 cursor c_descendants (l_process_id number) is
95 select parent_child_id
96 from amw_proc_hierarchy_denorm
97 where process_id = l_process_id and
98 up_down_ind = 'D';
99
100 type descendants_tbl is table of c_descendants%rowtype;
101 type relations_tbl is table of c_all_latest_relations%rowtype;
102
103
104 -- CURSOR TO FIND WHETHER THE A GIVEN RELATION EXISTS OR NOT..
105 cursor c_relation_exists (l_ancestor_id number,
106 l_descendant_id number) is
107 select 1 from amw_proc_hierarchy_denorm
108 where process_id = l_ancestor_id and
109 parent_child_id = l_descendant_id and
110 up_down_ind = 'D';
111
112 l_dummy number;
113 x_atbl ancestor_tbl;
114 x_dtbl descendants_tbl;
115 x_rtbl relations_tbl;
116 add_flag boolean;
117 add_flag1 boolean;
118 add_flag2 boolean;
119 add_flag3 boolean;
120
121
122
123 begin
124 x_index := 0;
125 x_process_tbl := process_tbl();
126 x_parent_child_tbl := parent_child_tbl();
127 x_up_down_ind_tbl := up_down_ind_tbl();
128 x_index_tbl.delete;
129
130
131 -- COLLECT ALL THE ANCESTORS OF THE PARENT INTO A TABLE..
132 open c_ancestors(p_parent_id);
133 fetch c_ancestors bulk collect into x_atbl;
134 close c_ancestors;
135
136 -- COLLECT ALL THE DESCENDENTS OF THE CHILD INTO A TABLE.
137 open c_descendants(p_child_id);
138 fetch c_descendants bulk collect into x_dtbl;
139 close c_descendants;
140
141
142 -- COLLECT ALL THE RELATIONS THAT EXISTS IN THE TABLE..
143 open c_all_latest_relations;
144 fetch c_all_latest_relations bulk collect into x_rtbl;
145 close c_all_latest_relations;
146
147
148 -- Store all the relations into an associative array..to transfer into the table later..
149
150 -- GET ALL THE RELATIONS THAT ALREADY IN THE HIERARCHY DENORM TABLE IN TO THE 'X_INDEX_TBL'.
151 --input all the relations into the associative array
152 if(x_rtbl.exists(1))
153 then
154 for ctr in x_rtbl.first .. x_rtbl.last loop
155 if(x_rtbl(ctr).up_down_ind = 'D') then
156 x_index_tbl(encode(x_rtbl(ctr).process_id,x_rtbl(ctr).parent_child_id)) := 1;
157 end if;
158 end loop;
159 end if;
160
161
162
163 -- CHECK IF THE PARENT-CHILD RELATION EXISTS ALREAY IN THE DENORM TABLE.
164 add_flag := true;
165 if(x_index_tbl.exists(encode(p_parent_id,p_child_id)))
166 then
167 add_flag := false;
168 end if;
169
170 -- IF NOT EXISTS ADD IT TO THE DENORM..(I.E. ADD IT TO INTURN ADD X_INDEX_TBL)
171 if (add_flag) then
172 add_rows_to_denorm(p_parent_id, p_child_id);
173
174 -- kosriniv YOU NEED TO DO IT FOR ALL THE ANCESTORS ALSO..
175 if(x_atbl.exists(1)) then
176 for ctr1 in x_atbl.first .. x_atbl.last loop
177 add_flag3 := true;
178 if(x_index_tbl.exists(encode(x_atbl(ctr1).parent_child_id,
179 p_child_id)))
180 then
181 add_flag3 := false;
182 end if;
183 if (add_flag3) then
184 add_rows_to_denorm(x_atbl(ctr1).parent_child_id,
185 p_child_id);
186 end if;
187 end loop;
188 -- ADDED ALL THE ANSCENDENT-DESCENDENTS LINKS..
189 end if;
190 -- IF ANY DESCENTS EXISTS FOR THE CHILD, YOU NEED TO ADD IT TO THEM TO THE HIERARHY DENORM ALSO..
191 if(x_dtbl.exists(1)) then
192 -- DO FOR ALL THE DESCNENDENTS..WITH THE PARENT
193 for ctr in x_dtbl.first .. x_dtbl.last loop
194 add_flag1 := true;
195 if(x_index_tbl.exists(encode(p_parent_id,x_dtbl(ctr).parent_child_id)))
196 then
197 add_flag1 := false;
198 end if;
199
200 if(add_flag1)
201 then
202 add_rows_to_denorm(p_parent_id,x_dtbl(ctr).parent_child_id);
203 -- IF YOU HAVE ANY ASSCENDENTS TO THE PARENT, YOU NEED TO ADD THE DESCENEDENTS TO THEM ALSO IN TO THE HIERARHCY DENORM...
204 if(x_atbl.exists(1)) then
205 for ctr1 in x_atbl.first .. x_atbl.last loop
206 add_flag2 := true;
207 if(x_index_tbl.exists(encode(x_atbl(ctr1).parent_child_id,
208 x_dtbl(ctr).parent_child_id)))
209 then
210 add_flag2 := false;
211 end if;
212 if (add_flag2) then
213 add_rows_to_denorm(x_atbl(ctr1).parent_child_id,
214 x_dtbl(ctr).parent_child_id);
215 end if;
216 end loop;
217 -- ADDED ALL THE ANSCENDENT-DESCENDENTS LINKS..
218 end if;
219 end if;
220 end loop;
221 end if;
222 end if;
223
224 --now insert all the rows found into the amw_proc_hierarchy_denorm table
225 if(x_process_tbl.exists(1))
226
227 then
228 forall i in x_process_tbl.first .. x_process_tbl.last
229 insert into amw_proc_hierarchy_denorm (PROCESS_ID,
230 PARENT_CHILD_ID,
231 UP_DOWN_IND,
232 LAST_UPDATE_DATE,
233 LAST_UPDATED_BY,
234 CREATION_DATE,
235 CREATED_BY,
236 LAST_UPDATE_LOGIN,
237 OBJECT_VERSION_NUMBER,
238 HIERARCHY_TYPE)
239 values
240 (x_process_tbl(i),
241 x_parent_child_tbl(i),
242 x_up_down_ind_tbl(i),
243 l_sysdate,
244 G_USER_ID,
245 l_sysdate,
246 G_USER_ID,
247 G_LOGIN_ID,
248 1,
249 'L');
250 end if;
251
252
253 exception
254 WHEN OTHERS THEN raise;
255
256
257 end update_denorm_add_child;
258
259
260
261
262
263
264 --assumes that x_index_tbl has been initialized before first call
265 procedure recursive_construct_denorm(p_process_id in number)
266
267 is
268
269 i pls_integer;
270
271
272 add_flag boolean;
273 add_flag1 boolean;
274
275 temp tn;
276 temp1 tn;
277
278 str varchar2(50);
279 begin
280
281 /* first get the children of p_process_id
282 * get it from the x_t1 table which stores these children
283 */
284
285 str := to_char(p_process_id);
286
287 if(x_t1.exists(str))
288 then
289 temp := x_t1(str);
290 else
291 temp := tn();
292 end if;
293
294 /* check to avoid numeric error */
295 if(temp.exists(1)) then
296
297 --for each child (of the process on which the procedure is called)
298 for i in temp.first .. temp.last loop
299
300 --first construct the denorm hierarchy for that child
301 recursive_construct_denorm( p_process_id => temp(i));
302
303
304 /* if the relationship between the process and the child does
305 * not already exist in the denorm table
306 * then add the two rows creating the relations
307 */
308 add_flag := true;
309
310 /* the x_index_tbl just check if we ever added an entry for
311 * <p_process_id>:<temp(i)>. If so it would never go process
312 * down further because all relations of process_id with the
313 * descendants of temp(i) would already have been added
314 */
315 if (x_index_tbl.exists(encode(p_process_id,temp(i))))
316 then
317 add_flag := false;
318 end if;
319
320
321
322 /* if the relation between p_process_id and temp(i)
323 * already existed in the relations table we dont need to even look into
324 * descendants of child_id .. else we look into them
325 * thus only if add_flag = true do any processing.
326 */
327 if (add_flag)
328 then
329 add_rows_to_denorm(p_process_id, temp(i));
330 --record this new descendant for p_process_id in the descendants array
331 x_t2(str).extend;
332 x_t2(str)(x_t2(str).last) := temp(i);
333
334 /* check if the child just processed has a single descendant
335 * if it doesnt have a single descendant then there is no need
336 * to process further in this recursive call
337 */
338 if(x_t2.exists(to_char(temp(i))))
339 then
340 --now temp1 points to the descendants of temp(i)
341 temp1 := x_t2(to_char(temp(i)));
342 else
343 temp1 := tn();
344 end if;
345
346
347
348
349 --check if necessary to look at descendants of child
350 if(temp1.exists(1))
351 then
352 --for each descendant
353 for ctr in temp1.first .. temp1.last loop
354 add_flag1 := true;
355
356 --is the p_process_id, temp1(ctr) relation already done?
357 if (x_index_tbl.exists(encode(p_process_id,temp1(ctr))))
358 then
359 add_flag1 := false;
360 end if;
361
362 --if fine to add the link between p_process_id and temp1(ctr)
363 if(add_flag1)
364
365 then
366 add_rows_to_denorm(p_process_id, temp1(ctr));
367
368 --record temp1(ctr) as a descendant of p_process_id
369 x_t2(str).extend;
370 x_t2(str)(x_t2(str).last) := temp1(ctr);
371 end if;
372 end loop;
373 end if;
374 end if;
375 end loop;
376 end if;
377
378
379
380 end recursive_construct_denorm;
381
382 /* this procedure assumes that the amw_approved_hierarchy
383 * table stores current data .. the entire denorm table is
384 * refreshed for the approved hierarchy
385 * for RL pass -1 as the p_org_id
386 */
387 procedure update_approved_denorm(p_org_id in number,
388 l_sysdate in Date default sysdate)
389 is
390
391 cursor c_all_approved_links_rl is
392 select parent_id, child_id
393 from amw_approved_hierarchies
394 where (organization_id is null or organization_id = -1)
395 and (end_date is null or end_date > l_sysdate);
396
397 cursor c_all_approved_links_org(l_org_id in number) is
398 select parent_id, child_id
399 from amw_approved_hierarchies
400 where (organization_id = l_org_id) and
401 (end_date is null or end_date > l_sysdate);
402
403 str varchar2(50);
404
405 begin
406 init;
407
408 if(p_org_id is null or p_org_id = -1)
409 then
410 open c_all_approved_links_rl;
411 fetch c_all_approved_links_rl bulk collect into p_links_tbl;
412 close c_all_approved_links_rl;
413 else
414 --ko removing the denorm usage..
415 return;
416 /*
417 open c_all_approved_links_org(p_org_id);
418 fetch c_all_approved_links_org bulk collect into p_links_tbl;
419 close c_all_approved_links_org;
420 */
421 end if;
422
423 -- Now if the p_links_tbl contains any data then
424 if p_links_tbl.exists(1) then
425 /* initialize the tables
426 * this is needed only for parents
427 * i.e only parents can have children and other descendants
428 */
429 for ctr in p_links_tbl.first .. p_links_tbl.last loop
430 str := to_char(p_links_tbl(ctr).parent_id);
431 x_t1(str) := tn();
432 x_t2(str) := tn();
433 end loop;
434
435 --put in all the links
436 for ctr in p_links_tbl.first .. p_links_tbl.last loop
437 str := to_char(p_links_tbl(ctr).parent_id);
438 x_t1(str).extend;
439 x_t1(str)(x_t1(str).last) := p_links_tbl(ctr).child_id;
440 end loop;
441
442
443 if(p_org_id is null or p_org_id = -1)
444 then
445 --make the pl/sql tables contain the up2date data
446 recursive_construct_denorm(p_process_id => -1);
447 --DML operations
448 delete from amw_proc_hierarchy_denorm where hierarchy_type='A';
449
450 else
451 recursive_construct_denorm(p_process_id => -2);
452
453 delete from amw_org_hierarchy_denorm
454 where organization_id = p_org_id and
455 hierarchy_type='A';
456 end if;
457
458
459 if(x_process_tbl.exists(1))
460
461 then
462 if(p_org_id is null or p_org_id = -1)
463
464 then
465 forall i in x_process_tbl.first .. x_process_tbl.last
466 insert into amw_proc_hierarchy_denorm (PROCESS_ID,
467 PARENT_CHILD_ID,
468 UP_DOWN_IND,
469 LAST_UPDATE_DATE,
470 LAST_UPDATED_BY,
471 CREATION_DATE,
472 CREATED_BY,
473 LAST_UPDATE_LOGIN,
474 OBJECT_VERSION_NUMBER,
475 HIERARCHY_TYPE)
476 values
477 (x_process_tbl(i),
478 x_parent_child_tbl(i),
479 x_up_down_ind_tbl(i),
480 l_sysdate,
481 G_USER_ID,
482 l_sysdate,
483 G_USER_ID,
484 G_LOGIN_ID,
485 1,
486 'A');
487 else --p_org_id is not null
488 forall i in x_process_tbl.first .. x_process_tbl.last
489 insert into amw_org_hierarchy_denorm (ORGANIZATION_ID,
490 PROCESS_ID,
491 PARENT_CHILD_ID,
492 UP_DOWN_IND,
493 LAST_UPDATE_DATE,
494 LAST_UPDATED_BY,
495 CREATION_DATE,
496 CREATED_BY,
497 LAST_UPDATE_LOGIN,
498 OBJECT_VERSION_NUMBER,
499 HIERARCHY_TYPE)
500 values
501 (p_org_id,
502 x_process_tbl(i),
503 x_parent_child_tbl(i),
504 x_up_down_ind_tbl(i),
505 l_sysdate,
506 G_USER_ID,
507 l_sysdate,
508 G_USER_ID,
509 G_LOGIN_ID,
510 1,
511 'A');
512 end if;
513 end if;
514 end if;
515 exception
516 WHEN OTHERS then
517 raise;
518
519
520 end update_approved_denorm;
521
522 procedure update_denorm(p_org_id in number,
523 l_sysdate in Date default sysdate)
524
525 is
526 --l_sysdate DATE := sysdate;
527 cursor c_top_level_rl is
528 (select distinct parent_id
529 from amw_latest_hierarchies
530 where (organization_id is null or organization_id = -1)
531 )
532 minus
533 (select distinct child_id parent_id
534 from amw_latest_hierarchies
535 where (organization_id is null or organization_id = -1)
536 );
537
538 cursor c_top_level_org(l_org_id in number) is
539 (select distinct parent_id
540 from amw_latest_hierarchies
541 where (organization_id = l_org_id)
542 )
543 minus
544 (select distinct child_id parent_id
545 from amw_latest_hierarchies
546 where (organization_id = l_org_id)
547 );
548
549
550 type ttbl is table of c_top_level_rl%rowtype;
551
552 p_tbl ttbl;
553 p_ltbl links_tbl;
554 l_batch_size pls_integer := 1000;
555 i pls_integer;
556 str varchar2(50);
557
558
559 begin
560
561
562
563
564 --initialize all global tables
565 init;
566
567 if(p_org_id is null or p_org_id = -1)
568 then
569 open c_top_level_rl;
570 fetch c_top_level_rl bulk collect into p_tbl;
571 close c_top_level_rl;
572 else
573 --ko removing the denorm usage..
574 return;
575 /*
576 open c_top_level_org(p_org_id);
577 fetch c_top_level_org bulk collect into p_tbl;
578 close c_top_level_org;
579 */
580 end if;
581
582
583 if(p_org_id is null or p_org_id = -1)
584 then
585 open c_all_latest_links_rl;
586 fetch c_all_latest_links_rl bulk collect into p_links_tbl;
587 close c_all_latest_links_rl;
588 else
589 --ko removing the denorm usage..
590 return;
591 /*
592 open c_all_latest_links_org(p_org_id);
593 fetch c_all_latest_links_org bulk collect into p_links_tbl;
594 close c_all_latest_links_org;
595 */
596 end if;
597
598
599
600 -- kosriniv check for p_links_tbl existance..
601 if p_links_tbl.exists(1) then
602
603
604 /* initialize the tables
605 * this is needed only for parents
606 * i.e only parents can have children and other descendants
607 */
608 for ctr in p_links_tbl.first .. p_links_tbl.last loop
609 str := to_char(p_links_tbl(ctr).parent_id);
610 x_t1(str) := tn();
611 x_t2(str) := tn();
612 end loop;
613
614 --put in all the links
615 for ctr in p_links_tbl.first .. p_links_tbl.last loop
616 str := to_char(p_links_tbl(ctr).parent_id);
617 x_t1(str).extend;
618 x_t1(str)(x_t1(str).last) := p_links_tbl(ctr).child_id;
619 end loop;
620
621 end if;
622 if(p_tbl.exists(1))
623
624 then
625
626 --call the updating procedure for each top level process
627 for i in p_tbl.first .. p_tbl.last loop
628 recursive_construct_denorm(p_process_id => p_tbl(i).parent_id);
629 end loop;
630 end if;
631
632
633 --delete all rows from the denorm table
634
635 if(p_org_id is null or p_org_id = -1)
636 then
637 delete from amw_proc_hierarchy_denorm where hierarchy_type='L';
638 else
639 delete from amw_org_hierarchy_denorm
640 where organization_id = p_org_id and
641 hierarchy_type='L';
642 end if;
643
644
645 if(x_process_tbl.exists(1))
646
647 then
648 if(p_org_id is null or p_org_id = -1)
649
650 then
651 forall i in x_process_tbl.first .. x_process_tbl.last
652 insert into amw_proc_hierarchy_denorm (PROCESS_ID,
653 PARENT_CHILD_ID,
654 UP_DOWN_IND,
655 LAST_UPDATE_DATE,
656 LAST_UPDATED_BY,
657 CREATION_DATE,
658 CREATED_BY,
659 LAST_UPDATE_LOGIN,
660 OBJECT_VERSION_NUMBER,
661 HIERARCHY_TYPE)
662 values
663 (x_process_tbl(i),
664 x_parent_child_tbl(i),
665 x_up_down_ind_tbl(i),
666 l_sysdate,
667 G_USER_ID,
668 l_sysdate,
669 G_USER_ID,
670 G_LOGIN_ID,
671 1,
672 'L');
673 else --p_org_id is not null
674 forall i in x_process_tbl.first .. x_process_tbl.last
675 insert into amw_org_hierarchy_denorm (ORGANIZATION_ID,
676 PROCESS_ID,
677 PARENT_CHILD_ID,
678 UP_DOWN_IND,
679 LAST_UPDATE_DATE,
680 LAST_UPDATED_BY,
681 CREATION_DATE,
682 CREATED_BY,
683 LAST_UPDATE_LOGIN,
684 OBJECT_VERSION_NUMBER,
685 HIERARCHY_TYPE)
686 values
687 (p_org_id,
688 x_process_tbl(i),
689 x_parent_child_tbl(i),
690 x_up_down_ind_tbl(i),
691 l_sysdate,
692 G_USER_ID,
693 l_sysdate,
694 G_USER_ID,
695 G_LOGIN_ID,
696 1,
697 'L');
698 end if;
699 end if;
700
701 exception
702 WHEN OTHERS then
703 raise;
704
705 end update_denorm;
706
707
708 procedure revise_process_if_necessary
709 (p_process_id in number,
710 l_sysdate in Date default sysdate)
711 is
712
713 l_process_id amw_process.process_id%type;
714 l_process_rev_id amw_process.process_rev_id%type;
715 l_item_type amw_process.item_type%type;
716 l_name amw_process.name%type;
717 l_process_code amw_process.process_code%type;
718 l_revision_number amw_process.revision_number%type;
719 l_approval_status amw_process.approval_status%type;
720 l_control_count amw_process.control_count%type;
721 l_risk_count amw_process.risk_count%type;
722 l_org_count amw_process.org_count%type;
723 l_significant_process_flag amw_process.significant_process_flag%type;
724 l_standard_process_flag amw_process.standard_process_flag%type;
725 l_certification_status amw_process.certification_status%type;
726 l_process_category amw_process.process_category%type;
727 l_process_owner_id amw_process.process_owner_id%type;
728 l_finance_owner_id amw_process.finance_owner_id%type;
729 l_application_owner_id amw_process.application_owner_id%type;
730 l_standard_variation amw_process.standard_variation%type;
731 l_deletion_date amw_process.deletion_date%type;
732 l_process_type amw_process.process_type%type;
733 l_control_activity_type amw_process.control_activity_type%type;
734 l_object_version_number amw_process.object_version_number%type;
735 l_attribute_category amw_process.attribute_category%type;
736 l_attribute1 amw_process.attribute1%type;
737 l_attribute2 amw_process.attribute2%type;
738 l_attribute3 amw_process.attribute3%type;
739 l_attribute4 amw_process.attribute4%type;
740 l_attribute5 amw_process.attribute5%type;
741 l_attribute6 amw_process.attribute6%type;
742 l_attribute7 amw_process.attribute7%type;
743 l_attribute8 amw_process.attribute8%type;
744 l_attribute9 amw_process.attribute9%type;
745 l_attribute10 amw_process.attribute10%type;
746 l_attribute11 amw_process.attribute11%type;
747 l_attribute12 amw_process.attribute12%type;
748 l_attribute13 amw_process.attribute13%type;
749 l_attribute14 amw_process.attribute14%type;
750 l_attribute15 amw_process.attribute15%type;
751
752 l_created_from amw_process.created_from%type;
753 l_program_update_date amw_process.program_update_date%type;
754 l_program_id amw_process.program_id%type;
755 l_program_application_id amw_process.program_application_id%type;
756 l_request_id amw_process.request_id%type;
757 l_risk_count_latest amw_process.risk_count_latest%type;
758 l_control_count_latest amw_process.control_count_latest%type;
759
760 l_new_process_rev_id number;
761
762 l_display_name amw_process_names_tl.display_name%type;
763 l_description amw_process_names_tl.description%type;
764 l_language amw_process_names_tl.language%type;
765 l_source_lang amw_process_names_tl.source_lang%type;
766
767 l_classification amw_process.classification%type;
768
769 -- l_sysdate DATE := sysdate;
770
771 l_dummy number;
772 begin
773 if(p_process_id <> -1)
774 then
775
776 select process_id, process_rev_id, item_type, name, process_code,
777 revision_number, approval_status, control_count,
778 risk_count, org_count, significant_process_flag,
779 standard_process_flag, certification_status,
780 process_category, process_owner_id, finance_owner_id,
781 application_owner_id, standard_variation,
782 object_version_number, deletion_date,
783 process_type, control_activity_type,
784 attribute_category, attribute1,
785 attribute2, attribute3, attribute4,
786 attribute5, attribute6, attribute7,
787 attribute8, attribute9, attribute10,
788 attribute11, attribute12, attribute13,
789 attribute14, attribute15, created_from,
790 program_id, program_application_id,
791 request_id, program_update_date, risk_count_latest,
792 control_count_latest, classification
793
794 into l_process_id, l_process_rev_id, l_item_type, l_name, l_process_code,
795 l_revision_number, l_approval_status, l_control_count,
796 l_risk_count, l_org_count, l_significant_process_flag,
797 l_standard_process_flag, l_certification_status,
798 l_process_category, l_process_owner_id, l_finance_owner_id,
799 l_application_owner_id, l_standard_variation,
800 l_object_version_number, l_deletion_date,
801 l_process_type, l_control_activity_type,
802 l_attribute_category, l_attribute1,
803 l_attribute2, l_attribute3, l_attribute4,
804 l_attribute5, l_attribute6, l_attribute7,
805 l_attribute8, l_attribute9, l_attribute10,
806 l_attribute11, l_attribute12, l_attribute13,
807 l_attribute14, l_attribute15, l_created_from,
808 l_program_id, l_program_application_id,
809 l_request_id, l_program_update_date,
810 l_risk_count_latest, l_control_count_latest,
811 l_classification
812
813
814 from amw_process
815
816 where process_id = p_process_id
817 and (end_date is null or end_date > l_sysdate);
818
819 /* any too_many_rows exception will propogate to caller */
820 if(sql%notfound)
821 then
822 raise FND_API.G_EXC_UNEXPECTED_ERROR;
823 end if;
824
825
826
827 if (l_approval_status='A')
828
829 --revise the parent process
830 then
831
832 insert into amw_process (PROCESS_ID,
833 ITEM_TYPE,
834 NAME,
835 PROCESS_CODE,
836 REVISION_NUMBER,
837 PROCESS_REV_ID,
838 APPROVAL_STATUS,
839 START_DATE,
840 CONTROL_COUNT,
841 RISK_COUNT,
842 ORG_COUNT,
843 SIGNIFICANT_PROCESS_FLAG,
844 STANDARD_PROCESS_FLAG,
845 CERTIFICATION_STATUS,
846 PROCESS_CATEGORY,
847 PROCESS_OWNER_ID,
848 FINANCE_OWNER_ID,
849 APPLICATION_OWNER_ID,
850 STANDARD_VARIATION,
851 LAST_UPDATE_DATE,
852 LAST_UPDATED_BY,
853 CREATION_DATE,
854 CREATED_BY,
855 LAST_UPDATE_LOGIN,
856 OBJECT_VERSION_NUMBER,
857 DELETION_DATE,
858 PROCESS_TYPE,
859 CONTROL_ACTIVITY_TYPE,
860 ATTRIBUTE_CATEGORY,
861 ATTRIBUTE1,
862 ATTRIBUTE2,
863 ATTRIBUTE3,
864 ATTRIBUTE4,
865 ATTRIBUTE5,
866 ATTRIBUTE6,
867 ATTRIBUTE7,
868 ATTRIBUTE8,
869 ATTRIBUTE9,
870 ATTRIBUTE10,
871 ATTRIBUTE11,
872 ATTRIBUTE12,
873 ATTRIBUTE13,
874 ATTRIBUTE14,
875 ATTRIBUTE15,
876 CREATED_FROM,
877 PROGRAM_ID,
878 PROGRAM_APPLICATION_ID,
879 REQUEST_ID,
880 PROGRAM_UPDATE_DATE,
881 RISK_COUNT_LATEST,
882 CONTROL_COUNT_LATEST,
883 CLASSIFICATION)
884
885 VALUES
886 (l_process_id,
887 l_item_type,
888 l_name,
889 l_process_code,
890 l_revision_number + 1,
891 AMW_PROCESS_S.nextval,
892 'D',
893 l_sysdate,
894 l_control_count,
895 l_risk_count,
896 l_org_count,
897 l_significant_process_flag,
898 l_standard_process_flag,
899 l_certification_status,
900 l_process_category,
901 l_process_owner_id,
902 l_finance_owner_id,
903 l_application_owner_id,
904 l_standard_variation,
905 l_sysdate,
906 G_USER_ID,
907 l_sysdate,
908 G_USER_ID,
909 G_LOGIN_ID,
910 1,
911 l_deletion_date,
912 l_process_type,
913 l_control_activity_type,
914 l_attribute_category,
915 l_attribute1,
916 l_attribute2,
917 l_attribute3,
918 l_attribute4,
919 l_attribute5,
920 l_attribute6,
921 l_attribute7,
922 l_attribute8,
923 l_attribute9,
924 l_attribute10,
925 l_attribute11,
926 l_attribute12,
927 l_attribute13,
928 l_attribute14,
929 l_attribute15,
930 l_created_from,
931 l_program_id,
932 l_program_application_id,
933 l_request_id,
934 l_program_update_date,
935 l_risk_count_latest,
936 l_control_count_latest,
937 l_classification)
938 RETURNING
939 PROCESS_REV_ID
940 INTO
941 l_new_process_rev_id;
942
943
944
945
946
947 update amw_process set
948 last_update_date = l_sysdate,
949 last_updated_by = G_USER_ID,
950 last_update_login = G_LOGIN_ID,
951 end_date = l_sysdate,
952 object_version_number = l_object_version_number + 1
953
954
955
956 where
957 process_id = p_process_id and
958 revision_number = l_revision_number and
959 object_version_number = l_object_version_number;
960
961
962 /* The only reason why the above insert could fail is:
963 * The object version number had already been incremented
964 * By some other process and thus the where clause failed to
965 * update any row
966 */
967 if(sql%notfound)
968 then
969 raise FND_API.G_EXC_ERROR;
970 end if;
971
972
973 --now update the translatable table
974 select display_name, description, language, source_lang
975
976 into l_display_name, l_description, l_language, l_source_lang
977
978 from amw_process_names_tl
979
980 where process_id = l_process_id and
981 revision_number = l_revision_number and
982 language = userenv('LANG');
983
984 /* too_many_rows will be propagated */
985 if(sql%notfound)
986 then
987 raise FND_API.G_EXC_UNEXPECTED_ERROR;
988 end if;
989
990
991
992 insert into amw_process_names_tl
993 (
994 process_id
995 ,revision_number
996 ,process_rev_id
997 ,display_name
998 ,description
999 ,language
1000 ,source_lang
1001 ,creation_date
1002 ,created_by
1003 ,last_update_date
1004 ,last_updated_by
1005 ,last_update_login
1006 ,object_version_number
1007 )
1008 select
1009 l_process_id
1010 ,l_revision_number+1
1011 ,l_new_process_rev_id
1012 ,l_display_name
1013 ,l_description
1014 ,L.LANGUAGE_CODE
1015 ,USERENV('LANG')
1016 ,l_sysdate
1017 ,g_user_id
1018 ,l_sysdate
1019 ,g_user_id
1020 ,g_login_id
1021 ,1
1022 from FND_LANGUAGES L
1023 where L.INSTALLED_FLAG in ('I', 'B');
1024
1025 --write code to copy attachments of the previous rev_id to the new one
1026 fnd_attached_documents2_pkg.copy_attachments(
1027 X_from_entity_name => 'AMW_PROCESS',
1028 X_from_pk1_value => l_process_rev_id,
1029 X_to_entity_name => 'AMW_PROCESS',
1030 X_to_pk1_value => l_new_process_rev_id,
1031 X_created_by => g_user_id,
1032 X_last_update_login => g_login_id,
1033 X_program_id => FND_GLOBAL.CONC_PROGRAM_ID,
1034 X_request_id => FND_GLOBAL.conc_request_id);
1035
1036
1037
1038
1039
1040
1041
1042 end if;
1043 end if;
1044
1045
1046
1047
1048 end revise_process_if_necessary;
1049
1050 /* this procedure updates the instance_id in the
1051 * amw_approved_hierarchy table if necessary
1052 * it should be called after a link is inserted in the
1053 * latest hierarchy (or an instance_id is updated)
1054 * the reason is that: the child order numbers of any
1055 * link in the latest and approved hierarchies MUST MATCH
1056 */
1057 procedure update_appr_ch_ord_num_if_reqd
1058 (p_org_id in number,
1059 p_parent_id in number,
1060 p_child_id in number,
1061 p_instance_id in number)
1062
1063 is
1064
1065 l_dummy pls_integer;
1066
1067 begin
1068
1069 select 1 into l_dummy from amw_approved_hierarchies
1070 where parent_id = p_parent_id
1071 and child_id = p_child_id
1072 and end_date is null
1073 and ((-1 = p_org_id and (organization_id is null or organization_id = -1)) OR
1074 (p_org_id <> -1 and organization_id = p_org_id));
1075
1076 update amw_approved_hierarchies set
1077 last_update_date = sysdate,
1078 last_updated_by = G_USER_ID,
1079 last_update_login = G_LOGIN_ID,
1080 child_order_number = p_instance_id,
1081 object_version_number = object_version_number + 1
1082 where parent_id = p_parent_id
1083 and child_id = p_child_id
1084 and end_date is null
1085 and ((-1 = p_org_id and (organization_id is null or organization_id = -1)) OR
1086 (p_org_id <> -1 and organization_id = p_org_id));
1087
1088 exception
1089 when too_many_rows then
1090 raise FND_API.G_EXC_UNEXPECTED_ERROR;
1091 when others then null;
1092
1093
1094 end update_appr_ch_ord_num_if_reqd;
1095
1096 function get_approval_status(p_process_id in number)
1097 return varchar2
1098 is
1099
1100 l_approval_status amw_process.approval_status%type;
1101 begin
1102 l_approval_status := 'D';
1103
1104 select approval_status into l_approval_status
1105 from amw_process where process_id = p_process_id and
1106 end_date is null;
1107
1108 return l_approval_status;
1109
1110
1111 exception
1112
1113 when others then
1114 return l_approval_status;
1115
1116 end get_approval_status;
1117
1118 --The parent process and the child process both exist as ICM processes
1119 procedure add_existing_process_as_child(
1120
1121 p_parent_process_id in number,
1122 p_child_process_id in number,
1123 l_sysdate in Date default sysdate,
1124 x_return_status out nocopy varchar2,
1125 x_msg_count out nocopy number,
1126 x_msg_data out nocopy varchar2)
1127
1128 is
1129
1130
1131 l_api_name constant varchar2(30) := 'add_existing_process_as_child';
1132
1133 p_init_msg_list varchar2(10) := FND_API.G_FALSE;
1134
1135 l_dummy pls_integer;
1136
1137 l_approval_status amw_process.approval_status%type;
1138
1139 l_child_order_number amw_latest_hierarchies.child_order_number%type;
1140
1141 CURSOR c1 is
1142 (select parent_process_id,
1143 child_process_id,
1144 child_order_number from AMW_LATEST_HIERARCHY_RL_V
1145 start with parent_process_id = -1 and
1146 parent_approval_status = 'A'
1147 connect by prior child_process_id = parent_process_id and
1148 child_approval_status = 'A' )
1149 MINUS
1150
1151 (select parent_process_id,
1152 child_process_id,
1153 child_order_number
1154 from AMW_CURR_APP_HIERARCHY_RL_V);
1155
1156
1157 begin
1158 x_return_status := FND_API.G_RET_STS_SUCCESS;
1159 if FND_API.to_Boolean(p_init_msg_list) then
1160 FND_MSG_PUB.initialize;
1161 end if;
1162
1163 if FND_GLOBAL.user_id is null then
1164 AMW_Utility_PVT.Error_Message(p_message_name => 'USER_PROFILE_MISSING');
1165 raise FND_API.G_EXC_ERROR;
1166 end if;
1167
1168 --check if parent_process_id is null
1169 if p_parent_process_id is null then
1170 raise FND_API.G_EXC_ERROR;
1171 end if;
1172
1173 --check if child_process_id is null
1174 if p_child_process_id is null then
1175 raise FND_API.G_EXC_ERROR;
1176 end if;
1177
1178
1179
1180
1181 --check if parent process is locked
1182 if (is_locked_process(p_parent_process_id))
1183 then
1184 raise amw_process_locked_exception;
1185 end if;
1186
1187
1188 /* check if the child is an ancestor of parent already
1189 * so that a circular hierarchy cannot be created
1190 */
1191 if(is_ancestor_in_hierarchy(p_child_process_id,p_parent_process_id))
1192 then
1193 raise amw_circularity_exception;
1194 end if;
1195
1196
1197 --we now check if this link is already existing in the latest hierarchy
1198
1199 open c_link_exist(p_parent_process_id,p_child_process_id);
1200 fetch c_link_exist into l_dummy;
1201 if(c_link_exist%found)
1202 then
1203 close c_link_exist;
1204 return;
1205 end if;
1206 close c_link_exist;
1207
1208 /* else, all is fine, we can proceed with revising the parent process
1209 * and creating the parent, child link in the latest hierarchy
1210 */
1211 revise_process_if_necessary(p_process_id => p_parent_process_id,
1212 l_sysdate => l_sysdate);
1213
1214
1215
1216
1217
1218 --update the latest hierarchy table
1219 insert into amw_latest_hierarchies(ORGANIZATION_ID,
1220 PARENT_ID,
1221 CHILD_ID,
1222 CHILD_ORDER_NUMBER,
1223 LAST_UPDATE_DATE,
1224 LAST_UPDATED_BY,
1225 LAST_UPDATE_LOGIN,
1226 CREATION_DATE,
1227 CREATED_BY,
1228 OBJECT_VERSION_NUMBER
1229 )
1230 VALUES (-1,
1231 p_parent_process_id,
1232 p_child_process_id,
1233 AMW_CHILD_ORDER_S.nextval,
1234 l_sysdate,
1235 g_user_id,
1236 g_login_id,
1237 l_sysdate,
1238 g_user_id,
1239 1)
1240 returning CHILD_ORDER_NUMBER
1241 into l_child_order_number;
1242
1243
1244 update_appr_ch_ord_num_if_reqd(-1, p_parent_process_id, p_child_process_id,
1245 l_child_order_number);
1246
1247
1248 /* update the denorm table
1249 * can throw an amw_processing_exception, so it has been handled.
1250 */
1251 update_denorm_add_child(p_parent_id => p_parent_process_id,
1252 p_child_id => p_child_process_id,
1253 l_sysdate => l_sysdate);
1254
1255 /* if the process was approved to begin with
1256 * and its parent was -1
1257 * then the approved hierarchy needs to be modified
1258 */
1259 l_approval_status := get_approval_status(p_child_process_id);
1260
1261 if(l_approval_status = 'A' and p_parent_process_id = -1)
1262
1263 then
1264 for a_link in c1 loop
1265 insert into amw_approved_hierarchies
1266 (organization_id,
1267 parent_id,
1268 child_id,
1269 start_date,
1270 child_order_number,
1271 LAST_UPDATE_DATE,
1272 LAST_UPDATED_BY,
1273 LAST_UPDATE_LOGIN,
1274 CREATION_DATE,
1275 CREATED_BY,
1276 OBJECT_VERSION_NUMBER)
1277 values
1278 (-1,
1279 a_link.parent_process_id,
1280 a_link.child_process_id,
1281 l_sysdate,
1282 a_link.child_order_number,
1283 l_sysdate,
1284 g_user_id,
1285 g_login_id,
1286 l_sysdate,
1287 g_user_id,
1288 1);
1289 end loop;
1290
1291 /* now update the denorm table */
1292 update_approved_denorm(-1,l_sysdate);
1293
1294 end if;
1295
1296
1297
1298 --Call the APIs to adjust the risk and control counts
1299 update_latest_control_counts(p_parent_process_id);
1300 update_latest_risk_counts(p_parent_process_id);
1301
1302
1303
1304
1305
1306 exception
1307 when FND_API.G_EXC_ERROR then
1308 ROLLBACK;
1309 x_return_status := FND_API.G_RET_STS_ERROR;
1310 FND_MSG_PUB.Count_And_Get(p_encoded => FND_API.G_FALSE,
1311 p_count => x_msg_count,
1312 p_data => x_msg_data);
1313
1314
1315 when FND_API.G_EXC_UNEXPECTED_ERROR then
1316 ROLLBACK;
1317 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
1318 FND_MSG_PUB.Count_And_Get(p_encoded => FND_API.G_FALSE,
1319 p_count => x_msg_count,
1320 p_data => x_msg_data);
1321
1322 when amw_process_locked_exception then
1323 x_return_status := FND_API.G_RET_STS_ERROR;
1324 x_msg_count := x_msg_count + 1;
1325 fnd_message.set_name('AMW','AMW_PROCESS_LOCKED');
1326 x_msg_data := fnd_message.get;
1327 fnd_msg_pub.add_exc_msg(p_pkg_name => G_PKG_NAME,
1328 p_procedure_name => 'add_existing_process_as_child',
1329 p_error_text => x_msg_data);
1330 raise FND_API.G_EXC_ERROR;
1331
1332
1333
1334
1335
1336 when amw_circularity_exception then
1337 x_return_status := FND_API.G_RET_STS_ERROR;
1338 fnd_message.set_name('AMW','AMW_CIRCULARITY_CREATION');
1339 x_msg_count := x_msg_count + 1;
1340 x_msg_data := fnd_message.get;
1341 fnd_msg_pub.add_exc_msg(p_pkg_name => G_PKG_NAME,
1342 p_procedure_name => 'add_existing_process_as_child',
1343 p_error_text => x_msg_count);
1344 raise FND_API.G_EXC_ERROR;
1345
1346
1347 when amw_processing_exception then
1348 ROLLBACK;
1349 x_return_status := FND_API.G_RET_STS_ERROR;
1350 FND_MSG_PUB.Count_And_Get(p_encoded => FND_API.G_FALSE,
1351 p_count => x_msg_count,
1352 p_data => x_msg_data);
1353
1354
1355 when OTHERS then
1356 ROLLBACK;
1357 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
1358
1359 FND_MSG_PUB.Count_And_Get(p_encoded => FND_API.G_FALSE,
1360 p_count => x_msg_count,
1361 p_data => x_msg_data);
1362
1363
1364
1365
1366
1367
1368
1369 end add_existing_process_as_child;
1370
1371
1372
1373
1374 procedure delete_child(
1375
1376 p_parent_process_id in number,
1377 p_child_process_id in number,
1378 l_sysdate in Date default sysdate,
1379 x_return_status out nocopy varchar2,
1380 x_msg_count out nocopy number,
1381 x_msg_data out nocopy varchar2)
1382
1383 is
1384
1385 l_api_name constant varchar2(30) := 'delete_child';
1386 p_init_msg_list varchar2(10) := FND_API.G_FALSE;
1387
1388 l_approval_status amw_process.approval_status%type;
1389
1390 l_dummy number;
1391
1392 CURSOR c3 is
1393 (select parent_process_id, child_process_id
1394 from AMW_CURR_APP_HIERARCHY_RL_V
1395 where parent_process_id is not null)
1396 MINUS
1397 (select parent_process_id, child_process_id
1398 from AMW_CURR_APP_HIERARCHY_RL_V
1399 start with parent_process_id = -1
1400 connect by prior child_process_id = parent_process_id);
1401 begin
1402 x_return_status := FND_API.G_RET_STS_SUCCESS;
1403 if FND_API.to_Boolean(p_init_msg_list) then
1404 FND_MSG_PUB.initialize;
1405 end if;
1406
1407 if FND_GLOBAL.user_id is null then
1408 raise FND_API.G_EXC_ERROR;
1409 end if;
1410
1411 --check if parent_process_id is null
1412 if p_parent_process_id is null then
1413 raise FND_API.G_EXC_ERROR;
1414 end if;
1415
1416
1417 --check if child_process_id is null
1418 if p_child_process_id is null then
1419 raise FND_API.G_EXC_ERROR;
1420 end if;
1421
1422 --check if parent process is locked
1423 if (is_locked_process(p_parent_process_id))
1424 then
1425 raise amw_process_locked_exception;
1426 end if;
1427
1428
1429
1430 /* check if the link exists: if it doesnt then this is an
1431 * unexpected error
1432 */
1433
1434 open c_link_exist(p_parent_process_id,p_child_process_id);
1435 fetch c_link_exist into l_dummy;
1436
1437 if(c_link_exist%notfound)
1438 then
1439 close c_link_exist;
1440 raise FND_API.G_EXC_UNEXPECTED_ERROR;
1441 end if;
1442
1443 close c_link_exist;
1444
1445
1446 /* revise the parent */
1447 revise_process_if_necessary(p_process_id => p_parent_process_id,
1448 l_sysdate => l_sysdate);
1449
1450
1451
1452
1453
1454
1455 /* update the latest hierarchy table
1456 * first we update the denorm table
1457 */
1458 delete from amw_latest_hierarchies
1459
1460 where
1461 parent_id = p_parent_process_id and
1462 child_id = p_child_process_id and
1463 (organization_id is null or organization_id = -1);
1464
1465
1466 if (sql%notfound)
1467 then
1468 raise FND_API.G_EXC_UNEXPECTED_ERROR;
1469 end if;
1470
1471
1472 update_denorm(p_org_id => -1,
1473 l_sysdate =>l_sysdate);
1474
1475
1476
1477 /* under some conditions the approved hierarchy
1478 * may need to be changed
1479 * the conditions is
1480 * The process is present under -1 in the approved hierarchy
1481 */
1482 begin
1483 select 1 into l_dummy from amw_approved_hierarchies
1484 where (organization_id is null or organization_id = -1)
1485 and parent_id = -1
1486 and child_id = p_child_process_id
1487 and end_date is null;
1488
1489 delete from amw_approved_hierarchies
1490 where parent_id = -1
1491 and child_id = p_child_process_id
1492 and (organization_id is null or organization_id = -1)
1493 and end_date is null;
1494
1495 /* run a cursor to remove defunct links */
1496 for defunct_link in c3 loop
1497 update amw_approved_hierarchies
1498 set end_date = l_sysdate,
1499 object_version_number = object_version_number + 1
1500 where (organization_id is null or organization_id = -1)
1501 and parent_id = defunct_link.parent_process_id
1502 and child_id = defunct_link.child_process_id
1503 and end_date is null;
1504 end loop;
1505
1506 /* finally update the denorm table */
1507 update_approved_denorm(-1,l_sysdate);
1508
1509
1510
1511 exception
1512 when no_data_found then null;
1513 when others then null;
1514
1515 end;
1516
1517 --Call the procedures to update the risk, control counts
1518 update_latest_control_counts(p_parent_process_id);
1519 update_latest_risk_counts(p_parent_process_id);
1520
1521
1522
1523
1524 exception
1525 when FND_API.G_EXC_ERROR then
1526 ROLLBACK;
1527 x_return_status := FND_API.G_RET_STS_ERROR;
1528 FND_MSG_PUB.Count_And_Get(p_encoded => FND_API.G_FALSE,
1529 p_count => x_msg_count,
1530 p_data => x_msg_data);
1531
1532
1533 when FND_API.G_EXC_UNEXPECTED_ERROR then
1534 ROLLBACK;
1535 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
1536 FND_MSG_PUB.Count_And_Get(p_encoded => FND_API.G_FALSE,
1537 p_count => x_msg_count,
1538 p_data => x_msg_data);
1539
1540 when amw_process_locked_exception then
1541 x_return_status := FND_API.G_RET_STS_ERROR;
1542 x_msg_count := x_msg_count + 1;
1543 fnd_message.set_name('AMW','AMW_PROCESS_LOCKED');
1544 x_msg_data := fnd_message.get;
1545 fnd_msg_pub.add_exc_msg(p_pkg_name => G_PKG_NAME,
1546 p_procedure_name => 'delete_child',
1547 p_error_text => x_msg_data);
1548 raise FND_API.G_EXC_ERROR;
1549
1550
1551 when amw_processing_exception then
1552 ROLLBACK;
1553 x_return_status := FND_API.G_RET_STS_ERROR;
1554 FND_MSG_PUB.Count_And_Get(p_encoded => FND_API.G_FALSE,
1555 p_count => x_msg_count,
1556 p_data => x_msg_data);
1557
1558
1559 when OTHERS then
1560 ROLLBACK;
1561 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
1562 FND_MSG_PUB.Count_And_Get(p_encoded => FND_API.G_FALSE,
1563 p_count => x_msg_count,
1564 p_data => x_msg_data);
1565
1566
1567
1568
1569
1570
1571
1572 end delete_child;
1573
1574
1575
1576
1577
1578
1579
1580 /* return TRUE is process is locked in RL: either because it is itself
1581 * submitted for approval or because some higher process is submitted
1582 * for approval and the approval profile option dictates locking of
1583 * all downward processes in the hierarchy.
1584 */
1585 function is_locked_process(p_process_id in number) return boolean is
1586
1587 cursor c_locks(l_process_id number) is
1588 select locked_process_id from amw_process_locks
1589 where (organization_id is null or organization_id=-1) and
1590 locked_process_id=l_process_id;
1591 l_dummy number;
1592 begin
1593 open c_locks(p_process_id);
1594 fetch c_locks into l_dummy;
1595 if(c_locks%notfound)
1596 then
1597 close c_locks;
1598 return false;
1599 end if;
1600
1601 close c_locks;
1602 return true;
1603
1604 end is_locked_process;
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622 /* this is called to get the process_id from the name and item
1623 * type. This function will RAISE AN EXCEPTION (not return null)
1624 * if it does not find such a process in amw_process table
1625 */
1626 function get_process_id_from_wf_params(p_name in varchar2,
1627 p_item_type in varchar2)
1628 return number is
1629
1630 l_process_id amw_process.process_id%type;
1631
1632 begin
1633
1634 select process_id into l_process_id from amw_process
1635 where name = p_name
1636 and item_type = p_item_type
1637 and end_date is null;
1638
1639
1640 return l_process_id;
1641 exception
1642 when others
1643 then raise FND_API.G_EXC_UNEXPECTED_ERROR;
1644
1645 end get_process_id_from_wf_params;
1646
1647 function does_wf_proc_exist_in_icm(p_name in varchar2,
1648 p_item_type in varchar2)
1649 return boolean is
1650
1651 l_dummy pls_integer;
1652
1653 begin
1654
1655 select 1 into l_dummy from amw_process
1656 where name = p_name
1657 and item_type = p_item_type
1658 and end_date is null;
1659
1660 return true;
1661
1662 exception
1663 when no_data_found then
1664 return false;
1665 when others then
1666 raise FND_API.G_EXC_UNEXPECTED_ERROR;
1667
1668 end does_wf_proc_exist_in_icm;
1669
1670 function get_process_code return varchar2
1671
1672 is
1673
1674
1675 l_code varchar2(100);
1676 l_dummy pls_integer;
1677
1678 l_prefix amw_parameters.parameter_value%type;
1679
1680 begin
1681
1682
1683 l_prefix := AMW_UTILITY_PVT.get_parameter(p_org_id => -1,
1684 p_param_name => 'PROCESS_CODE_PREFIX');
1685
1686
1687 while (true) loop
1688 select l_prefix || to_char(AMW_PROCESS_CODE_S.nextval) into l_code from dual;
1689
1690 select 1 into l_dummy from amw_process
1691 where process_code = l_code
1692 and end_date is null;
1693
1694 end loop;
1695
1696 exception
1697 when no_data_found then
1698 return l_code;
1699 when others then
1700 raise FND_API.G_EXC_UNEXPECTED_ERROR;
1701
1702
1703 end;
1704 /* create a new icm process and return the process_id */
1705 function create_new_icm_process(
1706 p_name in varchar2,
1707 p_item_type in varchar2,
1708 p_display_name in varchar2,
1709 p_description in varchar2)
1710
1711 return number
1712
1713 is
1714
1715 l_process_id amw_process.process_id%type;
1716 l_process_rev_id amw_process.process_rev_id%type;
1717 l_new_code amw_process.process_code%type;
1718 begin
1719 l_new_code := get_process_code;
1720
1721 insert into amw_process (PROCESS_ID,
1722 ITEM_TYPE,
1723 NAME,
1724 PROCESS_CODE,
1725 REVISION_NUMBER,
1726 PROCESS_REV_ID,
1727 APPROVAL_STATUS,
1728 START_DATE,
1729 CONTROL_COUNT,
1730 RISK_COUNT,
1731 ORG_COUNT,
1732 LAST_UPDATE_DATE,
1733 LAST_UPDATED_BY,
1734 CREATION_DATE,
1735 CREATED_BY,
1736 LAST_UPDATE_LOGIN,
1737 OBJECT_VERSION_NUMBER,
1738 PROCESS_TYPE,
1739 PROGRAM_ID,
1740 REQUEST_ID,
1741 PROGRAM_UPDATE_DATE,
1742 RISK_COUNT_LATEST,
1743 CONTROL_COUNT_LATEST,
1744 SIGNIFICANT_PROCESS_FLAG,
1745 STANDARD_PROCESS_FLAG,
1746 PROCESS_CATEGORY)
1747
1748 VALUES
1749 (AMW_PROCESS_S.nextval,
1750 p_item_type,
1751 p_name,
1752 l_new_code,
1753 1,
1754 AMW_PROCESS_S.nextval,
1755 'D',
1756 g_sysdate,
1757 0,
1758 0,
1759 0,
1760 g_sysdate,
1761 G_USER_ID,
1762 g_sysdate,
1763 G_USER_ID,
1764 G_LOGIN_ID,
1765 1,
1766 'P',
1767 FND_GLOBAL.CONC_PROGRAM_ID,
1768 FND_GLOBAL.CONC_REQUEST_ID,
1769 DECODE(FND_GLOBAL.CONC_PROGRAM_ID,null,null,g_sysdate),
1770 0,
1771 0,
1772 'Y',
1773 'Y',
1774 'R')
1775 RETURNING
1776 PROCESS_ID, PROCESS_REV_ID
1777 INTO
1778 l_process_id, l_process_rev_id;
1779
1780
1781 insert into amw_process_names_tl
1782 (
1783 process_id
1784 ,revision_number
1785 ,process_rev_id
1786 ,display_name
1787 ,description
1788 ,language
1789 ,source_lang
1790 ,creation_date
1791 ,created_by
1792 ,last_update_date
1793 ,last_updated_by
1794 ,last_update_login
1795 ,object_version_number
1796 )
1797 select
1798 l_process_id
1799 ,1
1800 ,l_process_rev_id
1801 ,p_display_name
1802 ,p_description
1803 ,L.LANGUAGE_CODE
1804 ,USERENV('LANG')
1805 ,g_sysdate
1806 ,g_user_id
1807 ,g_sysdate
1808 ,g_user_id
1809 ,g_login_id
1810 ,1
1811 from FND_LANGUAGES L
1812 where L.INSTALLED_FLAG in ('I', 'B');
1813
1814
1815 return l_process_id;
1816
1817 end create_new_icm_process;
1818
1819 function is_deleted_process(p_process_id in number)
1820 return boolean is
1821 l_dummy pls_integer;
1822 begin
1823 select 1 into l_dummy from amw_process
1824 where process_id = p_process_id
1825 and end_date is null
1826 and deletion_date is not null;
1827
1828 return true;
1829
1830 exception
1831 when no_data_found then
1832 return false;
1833 when others then
1834 raise;
1835
1836 end is_deleted_process;
1837
1838 /* @p_parent_process_id : the process_id of the parent process under which to add
1839 * @p_name : the name (from wf)
1840 * @p_item_type : the item_type(from wf)
1841 * @p_instance_id : the instance_id from WF
1842 * @p_overwrite_ex : 'Y' or 'N' telling whether or not to overwrite ICM defn.
1843 with WF definition
1844 */
1845
1846 procedure recursive_wf_import (p_parent_process_id in number,
1847 p_name in varchar2,
1848 p_item_type in varchar2,
1849 p_display_name in varchar2,
1850 p_description in varchar2,
1851 p_instance_id in number,
1852 p_overwrite_ex in varchar2)
1853
1854
1855 is
1856 cursor c_wf_children (l_name in varchar2, l_item_type in varchar2) is
1857 select activity_item_type, activity_name,
1858 activity_display_name, activity_description,
1859 instance_id
1860 from amw_wf_process_hierarchy_vl
1861 where process_name = l_name and
1862 process_item_type = l_item_type;
1863 type wf_children_tbl is table of c_wf_children%rowtype;
1864
1865 wfc_tbl wf_children_tbl;
1866
1867
1868 cursor c_wf_minus_icm(l_name in varchar2, l_item_type in varchar2) is
1869 (select activity_name, activity_item_type
1870 from amw_wf_process_hierarchy_vl
1871 where process_name = l_name
1872 and process_item_type = l_item_type
1873 )
1874 MINUS
1875 (select child_name activity_name, child_item_type activity_item_type
1876 from amw_latest_hierarchy_rl_v
1877 where parent_name = l_name
1878 and parent_item_type = l_item_type
1879 );
1880
1881 type wf_minus_icm_tbl is table of c_wf_minus_icm%rowtype;
1882 wf_diff_icm wf_minus_icm_tbl;
1883
1884 cursor c_icm_minus_wf(l_name in varchar2, l_item_type in varchar2) is
1885 (select child_name, child_item_type
1886 from amw_latest_hierarchy_rl_v
1887 where parent_name = l_name
1888 and parent_item_type = l_item_type
1889 )
1890 MINUS
1891 (select activity_name child_name, activity_item_type child_item_type
1892 from amw_wf_process_hierarchy_vl
1893 where process_name = l_name
1894 and process_item_type = l_item_type
1895 );
1896
1897 type icm_minus_wf_tbl is table of c_icm_minus_wf%rowtype;
1898 icm_diff_wf icm_minus_wf_tbl;
1899
1900
1901 CURSOR c1 is
1902 (select parent_process_id,
1903 child_process_id,
1904 child_order_number from AMW_LATEST_HIERARCHY_RL_V
1905 start with parent_process_id = -1 and
1906 parent_approval_status = 'A'
1907 connect by prior child_process_id = parent_process_id and
1908 child_approval_status = 'A' )
1909 MINUS
1910
1911 (select parent_process_id,
1912 child_process_id,
1913 child_order_number
1914 from AMW_CURR_APP_HIERARCHY_RL_V);
1915
1916
1917
1918
1919 indexing_str varchar2(40);
1920 -- whether am currently processing some recursive invocation on
1921 -- this name and item_type : then value is : 'VISITING'
1922 -- if for first time : value is 'ARRIVED'
1923 -- if already visited : value is 'VISITED'
1924
1925 visiting_status varchar2(8);
1926 l_process_id amw_process.process_id%type;
1927 l_dummy pls_integer;
1928 exist_in_icm boolean;
1929 cur_child_id amw_process.process_id%type;
1930 l_approval_status amw_process.approval_status%type;
1931 security_check varchar2(1);
1932
1933 begin
1934
1935 indexing_str := p_name || 'w' || p_item_type;
1936
1937 if(not visited_tbl.exists(indexing_str))
1938 then
1939 visiting_status := 'ARRIVED';
1940 elsif (visited_tbl(indexing_str) = 1)
1941 then
1942 visiting_status := 'VISITING';
1943 else
1944 visiting_status := 'VISITED';
1945 end if;
1946
1947
1948
1949 if(visiting_status = 'VISITING')
1950 then
1951 raise wf_cycle_present_exception;
1952 end if;
1953
1954 -- so visiting_status = 'ARRIVED' or 'VISITED'
1955 if(visiting_status = 'VISITED')
1956 then
1957 -- 1. Must add link in latest hierarchy unless present
1958 -- 2. Must add link in approved hierarchy if necessary
1959 -- 3. Must update instance_id of approved hierarchy if necessary
1960 -- 4. Must update the denorm table of approved hierarchy if a link was
1961 -- indeed added
1962
1963 -- FIRST: Get the process_id : it must be there since this node
1964 -- has already been visited.
1965 l_process_id := get_process_id_from_wf_params(p_name, p_item_type);
1966
1967 -- CHECK IF CIRCULARITY BEING CREATED ...
1968 -- Notice : circularity can be created only if
1969 -- this process and its parent were both in ICM before the
1970 -- recursive_wf_import began ... if circularity is through the
1971 -- wf hierarchy it will be detected as a cycle in wf ...
1972 -- hence the point is : we can rely on the non-updated
1973 -- denorm tables....
1974 if(is_ancestor_in_hierarchy(l_process_id, p_parent_process_id))
1975 then
1976 raise amw_circularity_exception;
1977 end if;
1978
1979
1980 -- If this link is not in latest hierachy we add it
1981 -- If it was present we do not do anything
1982 -- In particular we DO NOT UPDATE the child_order_number ..
1983 -- even though p_overwrite_ex may be 'Y'
1984 begin
1985 select 1 into l_dummy from amw_latest_hierarchies
1986 where parent_id = p_parent_process_id
1987 and child_id = l_process_id
1988 and (organization_id is null or organization_id = -1);
1989 exception
1990 when no_data_found
1991 then
1992 insert into amw_latest_hierarchies (ORGANIZATION_ID,
1993 PARENT_ID,
1994 CHILD_ID,
1995 CHILD_ORDER_NUMBER,
1996 LAST_UPDATE_DATE,
1997 LAST_UPDATED_BY,
1998 LAST_UPDATE_LOGIN,
1999 CREATION_DATE,
2000 CREATED_BY,
2001 OBJECT_VERSION_NUMBER
2002 )
2003 values (-1,
2004 p_parent_process_id,
2005 l_process_id,
2006 p_instance_id,
2007 g_sysdate,
2008 g_user_id,
2009 g_login_id,
2010 g_sysdate,
2011 g_user_id,
2012 1);
2013 update_appr_ch_ord_num_if_reqd(-1, p_parent_process_id,
2014 l_process_id,
2015 p_instance_id);
2016
2017 when others
2018 then raise;
2019 end;
2020
2021 -- In this block we would have added a link to approved_hierarchy if necessary
2022 -- The only case when this can be necessary is the following
2023 -- 1. p_parent_process_id = -1 and
2024 -- 2. the process with l_process_id is approved ...
2025 -- 3. However this is not possible because : since this process has been
2026 -- completely visited the calling parent process cannot be -1
2027 -- -1 can call this recursive procedure on only 1 child ....
2028 -- thus if that child was already completed ... this procedure
2029 -- cannot be called with -1 as the parent_process_id .. hence we do
2030 -- not need to check for addition to the approved hierarchy
2031
2032 return;
2033
2034 end if;
2035
2036 /* so here assume : visiting_status = 'ARRIVED' */
2037 --first change the visiting status to reflect visiting
2038 visited_tbl(indexing_str) := 1;
2039
2040 --check if process exist in ICM
2041 exist_in_icm := does_wf_proc_exist_in_icm(p_name,p_item_type);
2042
2043
2044 if(exist_in_icm)
2045 then
2046 --just need to add the links in the latest hierarchy if so needed ...
2047 l_process_id := get_process_id_from_wf_params(p_name, p_item_type);
2048
2049 if(is_deleted_process(l_process_id))
2050 then
2051 raise amw_process_deleted_exception;
2052 end if;
2053
2054 if(is_ancestor_in_hierarchy(l_process_id, p_parent_process_id))
2055 then
2056 raise amw_circularity_exception;
2057 end if;
2058
2059 --security check : the user needs to have appropriate privilege on this
2060 --process to be able to add it under a process on which the user has the
2061 --privilege!
2062
2063 security_check := amw_security_utils_pvt.check_function(p_function => 'AMW_UPD_RL_PROC'
2064 ,p_object_name => 'AMW_PROCESS_APPR_ETTY'
2065 ,p_instance_pk1_value => to_char(l_process_id)
2066 ,p_instance_pk2_value => '*NULL*'
2067 ,p_instance_pk3_value => '*NULL*'
2068 ,p_instance_pk4_value => '*NULL*'
2069 ,p_instance_pk5_value => '*NULL*');
2070 --it can be 'T', 'F', 'U' (unsupported API version)
2071 if (security_check <> 'T') then
2072 raise amw_insfcnt_prvlg_exception;
2073 end if;
2074
2075
2076
2077
2078 begin
2079 select 1 into l_dummy from amw_latest_hierarchies
2080 where parent_id = p_parent_process_id
2081 and child_id = l_process_id
2082 and (organization_id is null or organization_id = -1);
2083 exception
2084 when no_data_found then
2085 insert into amw_latest_hierarchies (ORGANIZATION_ID,
2086 PARENT_ID,
2087 CHILD_ID,
2088 CHILD_ORDER_NUMBER,
2089 LAST_UPDATE_DATE,
2090 LAST_UPDATED_BY,
2091 LAST_UPDATE_LOGIN,
2092 CREATION_DATE,
2093 CREATED_BY,
2094 OBJECT_VERSION_NUMBER)
2095 values (-1,
2096 p_parent_process_id,
2097 l_process_id,
2098 p_instance_id,
2099 g_sysdate,
2100 g_user_id,
2101 g_login_id,
2102 g_sysdate,
2103 g_user_id,
2104 1);
2105 update_appr_ch_ord_num_if_reqd(-1, p_parent_process_id,
2106 l_process_id,
2107 p_instance_id);
2108
2109 when others then
2110 raise;
2111 end;
2112
2113
2114
2115 if(p_overwrite_ex = 'N')
2116 then
2117 --dont have to follow the wf_hierarchy any further ...
2118
2119 --indicate that this node has been visited
2120 visited_tbl(indexing_str) := 2;
2121 return;
2122 else
2123
2124 --1. get process_id
2125 --2. Get icm_minus_wf and wf_minus_icm
2126 --3. if there is a difference ... then revise if necessary
2127 --4. update info abt links
2128 --5. for each check if appr_hierarchy needs to be updated
2129 --6. call recursive on each child
2130 --7. before returning indicate that you are done
2131
2132 open c_wf_minus_icm(p_name, p_item_type);
2133 open c_icm_minus_wf(p_name, p_item_type);
2134 fetch c_wf_minus_icm bulk collect into wf_diff_icm;
2135 fetch c_icm_minus_wf bulk collect into icm_diff_wf;
2136
2137
2138
2139 if(wf_diff_icm.exists(1) or icm_diff_wf.exists(1))
2140 then
2141 if(is_locked_process(l_process_id))
2142 then
2143 raise amw_process_locked_exception;
2144 end if;
2145 revise_process_if_necessary(p_process_id => l_process_id,
2146 l_sysdate => g_sysdate);
2147 end if;
2148
2149 --end_date all the links in icm_minus_wf
2150 if(icm_diff_wf.exists(1))
2151 then
2152 for ctr in icm_diff_wf.first .. icm_diff_wf.last loop
2153 cur_child_id := get_process_id_from_wf_params
2154 (icm_diff_wf(ctr).child_name,
2155 icm_diff_wf(ctr).child_item_type);
2156
2157 delete from amw_latest_hierarchies
2158 where (organization_id is null or organization_id = -1)
2159 and parent_id = l_process_id
2160 and child_id = cur_child_id;
2161 end loop;
2162 end if;
2163 close c_wf_minus_icm;
2164 close c_icm_minus_wf;
2165
2166 open c_wf_children(p_name, p_item_type);
2167 fetch c_wf_children bulk collect into wfc_tbl;
2168 if(wfc_tbl.exists(1))
2169 then
2170 for ctr in wfc_tbl.first .. wfc_tbl.last loop
2171 recursive_wf_import(p_parent_process_id => l_process_id,
2172 p_name => wfc_tbl(ctr).activity_name,
2173 p_item_type => wfc_tbl(ctr).activity_item_type,
2174 p_display_name => wfc_tbl(ctr).activity_display_name,
2175 p_description => wfc_tbl(ctr).activity_description,
2176 p_instance_id => wfc_tbl(ctr).instance_id,
2177 p_overwrite_ex => p_overwrite_ex);
2178 end loop;
2179 end if;
2180 close c_wf_children;
2181 end if;
2182 --there can be a case where the approved hierarchy needs to be changed
2183 --if the parent_process_id = -1 and the current procedure is approved ..
2184 --and will remain approved ...
2185 --however in this case this recursive invocation must be the first one itself
2186 --since parent_id = -1
2187
2188
2189 if(p_parent_process_id = -1)
2190 then
2191 select approval_status into l_approval_status
2192 from amw_process
2193 where process_id = l_process_id
2194 and end_date is null;
2195
2196 if(l_approval_status = 'A')
2197 then
2198 /* add link to approved hierarchy if not already there ... */
2199 for a_link in c1 loop
2200 insert into amw_approved_hierarchies
2201 (organization_id,
2202 parent_id,
2203 child_id,
2204 start_date,
2205 child_order_number,
2206 LAST_UPDATE_DATE,
2207 LAST_UPDATED_BY,
2208 LAST_UPDATE_LOGIN,
2209 CREATION_DATE,
2210 CREATED_BY,
2211 OBJECT_VERSION_NUMBER)
2212 values
2213 (-1,
2214 a_link.parent_process_id,
2215 a_link.child_process_id,
2216 g_sysdate,
2217 a_link.child_order_number,
2218 g_sysdate,
2219 g_user_id,
2220 g_login_id,
2221 g_sysdate,
2222 g_user_id,
2223 1);
2224 end loop;
2225
2226 /* now update the denorm table */
2227 update_approved_denorm(-1,g_sysdate);
2228 update_appr_control_counts;
2229 update_appr_risk_counts;
2230 end if;
2231
2232 end if;
2233
2234 visited_tbl(indexing_str) := 2;
2235 return;
2236
2237 end if;
2238 /* so process was not in ICM */
2239 --create a new process and add links ...
2240 --1. get the process_id of the newly created process
2241 --- and make the link from parent to child.
2242 --2. call recursively on each child
2243 --3. make links in latest hierarchy
2244 --4. before returning indicate that you are done ...
2245
2246 l_process_id := create_new_icm_process(p_name,p_item_type,p_display_name,
2247 p_description);
2248
2249
2250 insert into amw_latest_hierarchies (organization_id,
2251 parent_id,
2252 child_id,
2253 child_order_number,
2254 LAST_UPDATE_DATE,
2255 LAST_UPDATED_BY,
2256 LAST_UPDATE_LOGIN,
2257 CREATION_DATE,
2258 CREATED_BY,
2259 OBJECT_VERSION_NUMBER)
2260 values
2261 (-1,
2262 p_parent_process_id,
2263 l_process_id,
2264 p_instance_id,
2265 g_sysdate,
2266 g_user_id,
2267 g_login_id,
2268 g_sysdate,
2269 g_user_id,
2270 1);
2271
2272
2273
2274
2275
2276 /* loop and call recursively on each child in WF */
2277 open c_wf_children(p_name,p_item_type);
2278 fetch c_wf_children bulk collect into wfc_tbl;
2279
2280
2281
2282 if(wfc_tbl.exists(1))
2283 then
2284 for ctr in wfc_tbl.first .. wfc_tbl.last loop
2285 recursive_wf_import(p_parent_process_id => l_process_id,
2286 p_name => wfc_tbl(ctr).activity_name,
2287 p_item_type => wfc_tbl(ctr).activity_item_type,
2288 p_display_name => wfc_tbl(ctr).activity_display_name,
2289 p_description => wfc_tbl(ctr).activity_description,
2290 p_instance_id => wfc_tbl(ctr).instance_id,
2291 p_overwrite_ex => p_overwrite_ex);
2292 end loop;
2293 end if;
2294 close c_wf_children;
2295
2296 visited_tbl(indexing_str) := 2;
2297 return;
2298
2299 end recursive_wf_import;
2300
2301
2302 procedure import_wf_process(
2303 p_parent_process_id in number,
2304 p_comb_string in varchar2,
2305 p_overwrite_ex in varchar2,
2306 l_sysdate in Date default sysdate,
2307 p_update_denorm_count IN VARCHAR2 := 'Y',
2308 x_return_status out nocopy varchar2,
2309 x_msg_count out nocopy number,
2310 x_msg_data out nocopy varchar2)
2311 is
2312 iStart pls_integer := 1;
2313 iEnd pls_integer;
2314 cur_name wf_activities_vl.name%type;
2315 cur_item_type wf_activities_vl.item_type%type;
2316 cur_display_name wf_activities_vl.display_name%type;
2317 cur_description wf_activities_vl.description%type;
2318 cur_instance_id number;
2319
2320
2321 begin
2322 x_return_status := 'S';
2323 x_msg_count := 0;
2324 x_msg_data := '';
2325
2326 /* initializations for this procedure */
2327 g_sysdate := l_sysdate;
2328
2329 while (true) loop
2330 /* loop level initialization */
2331 visited_tbl.delete;
2332
2333 /* returns the position of first occurence of 'w' */
2334 iEnd := INSTR(p_comb_string, 'x', iStart);
2335 if(iEnd = 0)
2336 then
2337 exit;
2338 end if;
2339
2340 cur_name := substr(p_comb_string, iStart, iEnd-iStart);
2341 iStart := iEnd+1;
2342 iEnd := INSTR(p_comb_string, 'w', iStart);
2343 if(iEnd = 0)
2344 then
2345 iEnd := length(p_comb_string) + 1;
2346 end if;
2347 cur_item_type := substr(p_comb_string, iStart,iEnd-iStart);
2348 iStart := iEnd + 1;
2349
2350
2351 /* do your processing */
2352 select display_name, description, AMW_CHILD_ORDER_S.nextval
2353 into cur_display_name, cur_description, cur_instance_id
2354 from wf_activities_vl
2355 where name = cur_name
2356 and item_type = cur_item_type
2357 and end_date is null;
2358
2359
2360
2361
2362 recursive_wf_import(p_parent_process_id => p_parent_process_id,
2363 p_name => cur_name,
2364 p_item_type => cur_item_type,
2365 p_display_name => cur_display_name,
2366 p_description => cur_description,
2367 p_instance_id => cur_instance_id,
2368 p_overwrite_ex => p_overwrite_ex);
2369
2370
2371
2372
2373 end loop;
2374 IF p_update_denorm_count = 'Y' THEN
2375 /* update the denorm tables .. */
2376 update_denorm(p_org_id => -1,
2377 l_sysdate => g_sysdate);
2378
2379
2380 /* then update the risk_control_counts */
2381 update_all_latest_rc_counts(p_mode => 'RC');
2382 END IF;
2383
2384 exception
2385 when amw_process_locked_exception then
2386 ROLLBACK;
2387 x_return_status := FND_API.G_RET_STS_ERROR;
2388 x_msg_count := x_msg_count + 1;
2389 fnd_message.set_name('AMW','AMW_PROCESS_LOCKED');
2390 x_msg_data := fnd_message.get;
2391 fnd_msg_pub.add_exc_msg(p_pkg_name => G_PKG_NAME,
2392 p_procedure_name => 'import_wf_process',
2393 p_error_text => x_msg_data);
2394 raise FND_API.G_EXC_ERROR;
2395
2396 when amw_circularity_exception then
2397 ROLLBACK;
2398 x_return_status := FND_API.G_RET_STS_ERROR;
2399 x_msg_count := x_msg_count + 1;
2400 fnd_message.set_name('AMW','AMW_WF_CIRCULARITY_CREATION');
2401 x_msg_data := fnd_message.get;
2402 fnd_msg_pub.add_exc_msg(p_pkg_name => G_PKG_NAME,
2403 p_procedure_name => 'import_wf_process',
2404 p_error_text => x_msg_data);
2405 raise FND_API.G_EXC_ERROR;
2406
2407
2408 when amw_process_deleted_exception then
2409 ROLLBACK;
2410 x_return_status := FND_API.G_RET_STS_ERROR;
2411 x_msg_count := x_msg_count + 1;
2412 fnd_message.set_name('AMW','AMW_DELETED_PROC_MODIF');
2413 x_msg_data := fnd_message.get;
2414 fnd_msg_pub.add_exc_msg(p_pkg_name => G_PKG_NAME,
2415 p_procedure_name => 'import_wf_process',
2416 p_error_text => x_msg_data);
2417 raise FND_API.G_EXC_ERROR;
2418
2419 when amw_insfcnt_prvlg_exception then
2420 ROLLBACK;
2421 x_return_status := FND_API.G_RET_STS_ERROR;
2422 x_msg_count := x_msg_count + 1;
2423 fnd_message.set_name('AMW','AMW_INSFCNT_OPRN_PRVLG');
2424 x_msg_data := fnd_message.get;
2425 fnd_msg_pub.add_exc_msg(p_pkg_name => G_PKG_NAME,
2426 p_procedure_name => 'import_wf_process',
2427 p_error_text => x_msg_data);
2428 raise FND_API.G_EXC_ERROR;
2429
2430 when wf_cycle_present_exception then
2431 ROLLBACK;
2432 x_return_status := FND_API.G_RET_STS_ERROR;
2433 x_msg_count := x_msg_count + 1;
2434 fnd_message.set_name('AMW','AMW_CYCLE_IN_WF_HIERARCHY');
2435 x_msg_data := fnd_message.get;
2436 fnd_msg_pub.add_exc_msg(p_pkg_name => G_PKG_NAME,
2437 p_procedure_name => 'import_wf_process',
2438 p_error_text => x_msg_count);
2439 raise FND_API.G_EXC_ERROR;
2440
2441 when OTHERS then
2442 ROLLBACK;
2443 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
2444 FND_MSG_PUB.Count_And_Get(p_encoded => FND_API.G_FALSE,
2445 p_count => x_msg_count,
2446 p_data => x_msg_data);
2447 end import_wf_process;
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465 --THIS IS REALLY A MIRROR IMAGE OF add_exisiting_process_as_child PROCEDURE
2466 --WITH SOME CHANGES ....
2467 --The parent process and the child process both exist as ICM processes
2468 procedure add_WEBADI_HIERARCHY_LINKS(
2469 p_child_order_number in number,
2470 p_parent_process_id in number,
2471 p_child_process_id in number,
2472 l_sysdate in Date default sysdate,
2473 x_return_status out nocopy varchar2,
2474 x_msg_count out nocopy number,
2475 x_msg_data out nocopy varchar2)
2476
2477 is
2478
2479 l_api_name constant varchar2(30) := 'add_WEBADI_HIERARCHY_LINKS';
2480 p_init_msg_list varchar2(10) := FND_API.G_FALSE;
2481 l_dummy pls_integer;
2482 L_CHILD_ORDER NUMBER;
2483 l_approval_status amw_process.approval_status%type;
2484 l_child_order_number amw_latest_hierarchies.child_order_number%type;
2485
2486 CURSOR c1 is
2487 (select parent_process_id,
2488 child_process_id,
2489 child_order_number from AMW_LATEST_HIERARCHY_RL_V
2490 start with parent_process_id = -1 and
2491 parent_approval_status = 'A'
2492 connect by prior child_process_id = parent_process_id and
2493 child_approval_status = 'A' )
2494 MINUS
2495
2496 (select parent_process_id,
2497 child_process_id,
2498 child_order_number
2499 from AMW_CURR_APP_HIERARCHY_RL_V);
2500
2501
2502 begin
2503 ---05.23.2005 npanandi: commenting below log message
2504 ---FND_FILE.PUT_LINE(FND_FILE.LOG,'add_WEBADI_HIERARCHY_LINKS START');
2505 x_return_status := FND_API.G_RET_STS_SUCCESS;
2506 if FND_API.to_Boolean(p_init_msg_list) then
2507 FND_MSG_PUB.initialize;
2508 end if;
2509
2510 if FND_GLOBAL.user_id is null then
2511 AMW_Utility_PVT.Error_Message(p_message_name => 'USER_PROFILE_MISSING');
2512 raise FND_API.G_EXC_ERROR;
2513 end if;
2514
2515 --check if parent_process_id is null
2516 if p_parent_process_id is null then
2517 raise FND_API.G_EXC_ERROR;
2518 end if;
2519
2520 --check if child_process_id is null
2521 if p_child_process_id is null then
2522 raise FND_API.G_EXC_ERROR;
2523 end if;
2524
2525
2526
2527
2528 --check if parent process is locked
2529 if (is_locked_process(p_parent_process_id))
2530 then
2531 raise amw_process_locked_exception;
2532 end if;
2533
2534
2535 /* check if the child is an ancestor of parent already
2536 * so that a circular hierarchy cannot be created
2537 */
2538 if(is_ancestor_in_hierarchy(p_child_process_id,p_parent_process_id))
2539 then
2540 raise amw_circularity_exception;
2541 end if;
2542
2543
2544 --we now check if this link is already existing in the latest hierarchy
2545
2546 open c_link_exist(p_parent_process_id,p_child_process_id);
2547 fetch c_link_exist into l_dummy;
2548
2549
2550 if(c_link_exist%found)
2551 then
2552 close c_link_exist;
2553 return;
2554 end if;
2555 close c_link_exist;
2556
2557 /* else, all is fine, we can proceed with revising the parent process
2558 * and creating the parent, child link in the latest hierarchy
2559 */
2560 revise_process_if_necessary(p_process_id => p_parent_process_id,
2561 l_sysdate => l_sysdate);
2562
2563
2564
2565
2566
2567 --update the latest hierarchy table
2568 ---IF p_child_order_number IS -100, THIS MEANS THAT NO SEQ NUM WAS DEFINED BY USER
2569 --SO GENERATED VIA SEQUENCE
2570 IF(P_CHILD_ORDER_NUMBER = -100) THEN
2571 SELECT AMW_CHILD_ORDER_S.nextval INTO L_CHILD_ORDER FROM DUAL;
2572 ELSE
2573 L_CHILD_ORDER := P_CHILD_ORDER_NUMBER;
2574 END IF;
2575
2576 insert into amw_latest_hierarchies(ORGANIZATION_ID,
2577 PARENT_ID,
2578 CHILD_ID,
2579 CHILD_ORDER_NUMBER,
2580 LAST_UPDATE_DATE,
2581 LAST_UPDATED_BY,
2582 LAST_UPDATE_LOGIN,
2583 CREATION_DATE,
2584 CREATED_BY,
2585 OBJECT_VERSION_NUMBER)
2586 VALUES (-1,
2587 p_parent_process_id,
2588 p_child_process_id,
2589 L_CHILD_ORDER,
2590 l_sysdate,
2591 g_user_id,
2592 g_login_id,
2593 l_sysdate,
2594 g_user_id,
2595 1)
2596 returning CHILD_ORDER_NUMBER
2597 into l_child_order_number;
2598
2599
2600 update_appr_ch_ord_num_if_reqd(-1, p_parent_process_id, p_child_process_id,
2601 l_child_order_number);
2602
2603
2604 /* update the denorm table
2605 * can throw an amw_processing_exception, so it has been handled.
2606 */
2607 ---COMMENTING THE BELOW ... DON'T NEED THIS FROM WEBADI
2608 /*
2609 update_denorm_add_child(p_parent_id => p_parent_process_id,
2610 p_child_id => p_child_process_id,
2611 l_sysdate => l_sysdate);
2612 */
2613
2614 /* if the process was approved to begin with
2615 * and its parent was -1
2616 * then the approved hierarchy needs to be modified
2617 */
2618 select approval_status into l_approval_status
2619 from amw_process where process_id = p_child_process_id and
2620 end_date is null;
2621
2622 if(l_approval_status = 'A' and p_parent_process_id = -1)
2623
2624 then
2625 for a_link in c1 loop
2626 insert into amw_approved_hierarchies
2627 (organization_id,
2628 parent_id,
2629 child_id,
2630 start_date,
2631 child_order_number,
2632 LAST_UPDATE_DATE,
2633 LAST_UPDATED_BY,
2634 LAST_UPDATE_LOGIN,
2635 CREATION_DATE,
2636 CREATED_BY,
2637 OBJECT_VERSION_NUMBER)
2638 values
2639 (-1,
2640 a_link.parent_process_id,
2641 a_link.child_process_id,
2642 l_sysdate,
2643 a_link.child_order_number,
2644 l_sysdate,
2645 g_user_id,
2646 g_login_id,
2647 l_sysdate,
2648 g_user_id,
2649 1);
2650 end loop;
2651
2652 /* now update the denorm table */
2653 update_approved_denorm(-1,l_sysdate);
2654
2655 end if;
2656
2657 ---05.23.2005 npanandi: commenting below log message
2658 ---FND_FILE.PUT_LINE(FND_FILE.LOG,'add_WEBADI_HIERARCHY_LINKS END');
2659
2660 --Call the APIs to adjust the risk and control counts
2661 --COMMENTING THE BELOW .... DON'T NEED THIS WHEN CALLING FROM WEBADI
2662 ---update_latest_control_counts(p_parent_process_id);
2663 ---update_latest_risk_counts(p_parent_process_id);
2664
2665 exception
2666 when FND_API.G_EXC_ERROR then
2667 ROLLBACK;
2668 x_return_status := FND_API.G_RET_STS_ERROR;
2669 FND_MSG_PUB.Count_And_Get(p_encoded => FND_API.G_FALSE,
2670 p_count => x_msg_count,
2671 p_data => x_msg_data);
2672
2673
2674 when FND_API.G_EXC_UNEXPECTED_ERROR then
2675 ROLLBACK;
2676 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
2677 FND_MSG_PUB.Count_And_Get(p_encoded => FND_API.G_FALSE,
2678 p_count => x_msg_count,
2679 p_data => x_msg_data);
2680
2681 when amw_process_locked_exception then
2682 x_return_status := FND_API.G_RET_STS_ERROR;
2683 x_msg_count := x_msg_count + 1;
2684 fnd_message.set_name('AMW','AMW_PROCESS_LOCKED');
2685 x_msg_data := fnd_message.get;
2686 fnd_msg_pub.add_exc_msg(p_pkg_name => G_PKG_NAME,
2687 p_procedure_name => 'add_WEBADI_HIERARCHY_LINKS',
2688 p_error_text => x_msg_data);
2689 raise FND_API.G_EXC_ERROR;
2690
2691
2692
2693
2694
2695 when amw_circularity_exception then
2696 x_return_status := FND_API.G_RET_STS_ERROR;
2697 x_msg_count := x_msg_count + 1;
2698 fnd_message.set_name('AMW','AMW_CIRCULARITY_CREATION');
2699 x_msg_data := fnd_message.get;
2700 fnd_msg_pub.add_exc_msg(p_pkg_name => G_PKG_NAME,
2701 p_procedure_name => 'add_WEBADI_HIERARCHY_LINKS',
2702 p_error_text => x_msg_data);
2703 raise FND_API.G_EXC_ERROR;
2704
2705
2706 when amw_processing_exception then
2707 ROLLBACK;
2708 x_return_status := FND_API.G_RET_STS_ERROR;
2709 FND_MSG_PUB.Count_And_Get(p_encoded => FND_API.G_FALSE,
2710 p_count => x_msg_count,
2711 p_data => x_msg_data);
2712
2713
2714 when OTHERS then
2715 ROLLBACK;
2716 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
2717
2718 FND_MSG_PUB.Count_And_Get(p_encoded => FND_API.G_FALSE,
2719 p_count => x_msg_count,
2720 p_data => x_msg_data);
2721
2722 end add_WEBADI_HIERARCHY_LINKS;
2723
2724
2725
2726 ----------------------------COUNT UPDATE API's---------------------------------------------
2727 /* update the approved risk counts for all processes above
2728 * p_process_id in RL Approved Hierarchy
2729 * Call this ONLY AFTER making the denorm tables reflect
2730 * the current denormed approved hierarchy
2731 * This can be called for post approval processing
2732 *** BE CAREFUL WITH THE USE OF THIS PROCEDURE ***
2733 * This process only affects procedures in the approved_hierarchy
2734 * The approved_hierarchy is always connected to the root
2735 * It is possible that a process was approved and yet not present
2736 * in the approved hierarchy. Thus after some process P was approved
2737 * and its child Q (approved earlier) was added to the approved
2738 * hierarchy WHEN P was approved: IF THIS PROCEDURE WAS CALLED ONLY FOR
2739 * P it will not affect Q and the final result would be INCORRECT.
2740 */
2741 procedure update_approved_risk_counts(p_process_id in number)
2742 is
2743
2744
2745 cursor c is
2746 (select process_id from amw_process where process_id in
2747 ((select parent_child_id
2748 from amw_proc_hierarchy_denorm
2749 where process_id = p_process_id
2750 and up_down_ind = 'U'
2751 and hierarchy_type = 'A'
2752 )
2753 union all
2754 (select p_process_id from dual)));
2755 type t_n is table of number;
2756 x t_n;
2757 begin
2758 open c;
2759 fetch c bulk collect into x;
2760 close c;
2761
2762 if x.exists(1) then
2763 forall ctr in x.first .. x.last
2764 update amw_process
2765 set risk_count = (select count(*) from (
2766 select distinct risk_id from amw_risk_associations
2767 where pk1 in ( ( select parent_child_id
2768 from amw_proc_hierarchy_denorm
2769 where process_id = x(ctr)
2770 and up_down_ind = 'D'
2771 and hierarchy_type = 'A') union all (select x(ctr) from dual) )
2772 and approval_date is not null
2773 and deletion_approval_date is null
2774 and object_type = 'PROCESS'
2775 ) ),
2776 object_version_number = object_version_number + 1,
2777 last_update_date = sysdate,
2778 last_updated_by = G_USER_ID,
2779 last_update_login = G_LOGIN_ID
2780 where process_id = x(ctr)
2781 and approval_date is not null
2782 and approval_end_date is null
2783 and process_id <> -1;
2784 end if;
2785
2786 exception
2787
2788 when others
2789 then raise FND_API.G_EXC_UNEXPECTED_ERROR;
2790
2791 end update_approved_risk_counts;
2792
2793
2794 /* update the approved control counts for all processes above
2795 * p_process_id in RL Approved Hierarchy
2796 * Call this ONLY AFTER making the denorm tables reflect
2797 * the current denormed approved hierarchy
2798 * This can be called for post approval processing
2799 *** BE CAREFUL WITH THE USE OF THIS PROCEDURE ***
2800 * This process only affects procedures in the approved_hierarchy
2801 * The approved_hierarchy is always connected to the root
2802 * It is possible that a process was approved and yet not present
2803 * in the approved hierarchy. Thus after some process P was approved
2804 * and its child Q (approved earlier) was added to the approved
2805 * hierarchy WHEN P was approved: IF THIS PROCEDURE WAS CALLED ONLY FOR
2806 * P it will not affect Q and the final result would be INCORRECT.
2807 */
2808 procedure update_approved_control_counts(p_process_id in number)
2809 is
2810 cursor c is
2811 (select process_id from amw_process where process_id in
2812 ((select parent_child_id
2813 from amw_proc_hierarchy_denorm
2814 where process_id = p_process_id
2815 and up_down_ind = 'U'
2816 and hierarchy_type = 'A'
2817 )
2818 union all
2819 (select p_process_id from dual)));
2820
2821 type t_n is table of number;
2822 x t_n;
2823 begin
2824 open c;
2825 fetch c bulk collect into x;
2826 close c;
2827
2828 if x.exists(1) then
2829 forall ctr in x.first .. x.last
2830 update amw_process
2831 set control_count = (select count(*) from (
2832 select distinct control_id from amw_control_associations
2833 where pk1 in ( ( select parent_child_id
2834 from amw_proc_hierarchy_denorm
2835 where process_id = x(ctr)
2836 and up_down_ind = 'D'
2837 and hierarchy_type = 'A') union all (select x(ctr) from dual) )
2838 and approval_date is not null
2839 and deletion_approval_date is null
2840 and object_type = 'RISK'
2841 ) ),
2842 object_version_number = object_version_number + 1,
2843 last_update_date = sysdate,
2844 last_updated_by = G_USER_ID,
2845 last_update_login = G_LOGIN_ID
2846 where process_id = x(ctr)
2847 and approval_date is not null
2848 and approval_end_date is null
2849 and process_id <> -1;
2850 end if;
2851
2852 exception
2853
2854 when others
2855 then raise FND_API.G_EXC_UNEXPECTED_ERROR;
2856
2857 end update_approved_control_counts;
2858
2859
2860
2861 /* updates risk counts for every process in
2862 * the approved hierarchy
2863 */
2864 procedure update_appr_risk_counts is
2865
2866 cursor c is
2867 (select process_id from amw_process where process_id in
2868 (select parent_child_id
2869 from amw_proc_hierarchy_denorm
2870 where process_id = -1
2871 and up_down_ind = 'D'
2872 and hierarchy_type = 'A'
2873 ));
2874 type t_n is table of number;
2875 x t_n;
2876 begin
2877 open c;
2878 fetch c bulk collect into x;
2879 close c;
2880
2881 if x.exists(1) then
2882 forall ctr in x.first .. x.last
2883 update amw_process
2884 set risk_count = (select count(*) from (
2885 select distinct risk_id from amw_risk_associations
2886 where pk1 in ( ( select parent_child_id
2887 from amw_proc_hierarchy_denorm
2888 where process_id = x(ctr)
2889 and up_down_ind = 'D'
2890 and hierarchy_type = 'A') union all (select x(ctr) from dual) )
2891 and approval_date is not null
2892 and deletion_approval_date is null
2893 and object_type = 'PROCESS'
2894 ) ),
2895 object_version_number = object_version_number + 1,
2896 last_update_date = sysdate,
2897 last_updated_by = G_USER_ID,
2898 last_update_login = G_LOGIN_ID
2899 where process_id = x(ctr)
2900 and approval_date is not null
2901 and approval_end_date is null
2902 and process_id <> -1;
2903 end if;
2904
2905 exception
2906
2907 when others
2908 then raise FND_API.G_EXC_UNEXPECTED_ERROR;
2909
2910 end update_appr_risk_counts;
2911
2912 procedure update_appr_control_counts is
2913 cursor c is
2914 (select process_id from amw_process where process_id in
2915 (select parent_child_id
2916 from amw_proc_hierarchy_denorm
2917 where process_id = -1
2918 and up_down_ind = 'D'
2919 and hierarchy_type = 'A'
2920 ));
2921 type t_n is table of number;
2922 x t_n;
2923
2924 begin
2925
2926 open c;
2927 fetch c bulk collect into x;
2928 close c;
2929
2930 if x.exists(1) then
2931 forall ctr in x.first .. x.last
2932 update amw_process
2933 set control_count = (select count(*) from (
2934 select distinct control_id from amw_control_associations
2935 where pk1 in ( (select parent_child_id
2936 from amw_proc_hierarchy_denorm
2937 where process_id = x(ctr)
2938 and up_down_ind = 'D'
2939 and hierarchy_type = 'A') union all (select x(ctr) from dual) )
2940 and approval_date is not null
2941 and deletion_approval_date is null
2942 and object_type = 'RISK'
2943 ) )
2944 ,object_version_number = object_version_number + 1,
2945 last_update_date = sysdate,
2946 last_updated_by = G_USER_ID,
2947 last_update_login = G_LOGIN_ID
2948 where process_id = x(ctr)
2949 and approval_date is not null
2950 and approval_end_date is null
2951 and process_id <> -1;
2952 end if;
2953
2954 exception
2955
2956 when others
2957 then raise FND_API.G_EXC_UNEXPECTED_ERROR;
2958
2959
2960 end update_appr_control_counts;
2961
2962
2963
2964
2965 /* update the latest control counts for all processes above
2966 * p_process_id in RL
2967 * Call this ONLY AFTER making the denorm tables reflect
2968 * the current denormed hierarchy
2969 */
2970 procedure update_latest_control_counts(p_process_id in number)
2971 is
2972
2973 cursor c is
2974 (select process_id from amw_process where process_id in
2975 (select parent_child_id
2976 from amw_proc_hierarchy_denorm
2977 where process_id = p_process_id
2978 and up_down_ind = 'U'
2979 and hierarchy_type = 'L'
2980 ) union all
2981 (select p_process_id from dual));
2982 type t_n is table of number;
2983 x t_n;
2984 begin
2985 open c;
2986 fetch c bulk collect into x;
2987 close c;
2988
2989 if x.exists(1) then
2990 forall ctr in x.first .. x.last
2991 update amw_process
2992 set control_count_latest = (select count(*) from (
2993 select distinct control_id from amw_control_associations
2994 where pk1 in ( ( select parent_child_id
2995 from amw_proc_hierarchy_denorm
2996 where process_id = x(ctr)
2997 and up_down_ind = 'D'
2998 and hierarchy_type = 'L') union all (select x(ctr) from dual) )
2999 and deletion_date is null
3000 and object_type = 'RISK'
3001 ) )
3002 --unsure whether FWK validation may throw error if ovn is incremented here
3003 --so am removing it here.
3004 --.object_version_number = object_version_number + 1,
3005 ,last_update_date = sysdate
3006 ,last_updated_by = G_USER_ID
3007 ,last_update_login = G_LOGIN_ID
3008 where process_id = x(ctr)
3009 and end_date is null
3010 and process_id <> -1;
3011 end if;
3012
3013
3014
3015 exception
3016
3017 when others
3018 then raise FND_API.G_EXC_UNEXPECTED_ERROR;
3019
3020 end update_latest_control_counts;
3021
3022
3023 procedure update_latest_risk_counts(p_process_id in number)
3024 is
3025 cursor c is
3026 (select process_id from amw_process where process_id in
3027 (select parent_child_id
3028 from amw_proc_hierarchy_denorm
3029 where process_id = p_process_id
3030 and up_down_ind = 'U'
3031 and hierarchy_type = 'L'
3032 ) union all
3033 (select p_process_id from dual));
3034 type t_n is table of number;
3035 x t_n;
3036
3037 begin
3038
3039 open c;
3040 fetch c bulk collect into x;
3041 close c;
3042
3043 if x.exists(1) then
3044 forall ctr in x.first .. x.last
3045 update amw_process
3046 set risk_count_latest = (select count(*) from (
3047 select distinct risk_id from amw_risk_associations
3048 where pk1 in ( (select parent_child_id
3049 from amw_proc_hierarchy_denorm
3050 where process_id = x(ctr)
3051 and up_down_ind = 'D'
3052 and hierarchy_type = 'L') union all (select x(ctr) from dual) )
3053 and deletion_date is null
3054 and object_type = 'PROCESS'
3055 ) )
3056 --,object_version_number = object_version_number + 1
3057 ,last_update_date = sysdate
3058 ,last_updated_by = G_USER_ID
3059 ,last_update_login = G_LOGIN_ID
3060 where process_id = x(ctr)
3061 and end_date is null
3062 and process_id <> -1;
3063 end if;
3064
3065 exception
3066
3067 when others
3068 then raise FND_API.G_EXC_UNEXPECTED_ERROR;
3069
3070 end update_latest_risk_counts;
3071
3072
3073 /* This is only being used by my Java API
3074 * assumes that a rollback on error will be done from the caller
3075 * please keep this in mind when using
3076 */
3077 procedure update_rc_latest_counts(p_process_id in number,
3078 x_return_status out nocopy varchar2,
3079 x_msg_count out nocopy number,
3080 x_msg_data out nocopy varchar2)
3081
3082 is
3083
3084
3085
3086
3087 l_api_name constant varchar2(30) := 'update_rc_latest_counts';
3088
3089 p_init_msg_list varchar2(10) := FND_API.G_FALSE;
3090
3091 begin
3092 x_return_status := FND_API.G_RET_STS_SUCCESS;
3093 if FND_API.to_Boolean(p_init_msg_list) then
3094 FND_MSG_PUB.initialize;
3095 end if;
3096
3097 if FND_GLOBAL.user_id is null then
3098 AMW_Utility_PVT.Error_Message(p_message_name => 'USER_PROFILE_MISSING');
3099 raise FND_API.G_EXC_ERROR;
3100 end if;
3101
3102
3103 update_latest_risk_counts(p_process_id => p_process_id);
3104 update_latest_control_counts(p_process_id => p_process_id);
3105
3106 exception
3107 when others then
3108 x_return_status := FND_API.G_RET_STS_ERROR;
3109 FND_MSG_PUB.Count_And_Get(p_encoded => FND_API.G_FALSE,
3110 p_count => x_msg_count,
3111 p_data => x_msg_data);
3112 end update_rc_latest_counts;
3113
3114
3115
3116 /* update the latest risk-control counts for ALL processes in RL */
3117 procedure update_all_latest_rc_counts(p_mode in varchar2)
3118
3119 is
3120 cursor c is
3121 (select process_id from amw_process where end_date is null and process_id <> -1);
3122 type t_n is table of number;
3123 x t_n;
3124
3125 begin
3126 open c;
3127 fetch c bulk collect into x;
3128 close c;
3129
3130 if x.exists(1) then
3131 if(p_mode = 'R')
3132 then
3133 forall ctr in x.first .. x.last
3134 update amw_process
3135 set risk_count_latest = (select count(*) from (
3136 select distinct risk_id
3137 from amw_risk_associations
3138 where pk1 in ((select parent_child_id
3139 from amw_proc_hierarchy_denorm
3140 where process_id = x(ctr)
3141 and up_down_ind = 'D'
3142 and hierarchy_type = 'L') union all (select x(ctr) from dual) )
3143 and deletion_date is null
3144 and object_type = 'PROCESS'
3145 )),
3146 object_version_number = object_version_number + 1
3147 ,last_update_date = sysdate
3148 ,last_updated_by = G_USER_ID
3149 ,last_update_login = G_LOGIN_ID
3150 where process_id = x(ctr)
3151 and end_date is null;
3152
3153 elsif (p_mode = 'C')
3154 then
3155 forall ctr in x.first .. x.last
3156 update amw_process
3157 set control_count_latest = (select count(*) from
3158
3159 (select distinct control_id from amw_control_associations
3160 where pk1 in ((select parent_child_id
3161 from amw_proc_hierarchy_denorm
3162 where process_id = x(ctr)
3163 and up_down_ind = 'D'
3164 and hierarchy_type = 'L') union all (select x(ctr) from dual) )
3165 and deletion_date is null
3166 and object_type = 'RISK'
3167 )),
3168 object_version_number = object_version_number + 1
3169 ,last_update_date = sysdate
3170 ,last_updated_by = G_USER_ID
3171 ,last_update_login = G_LOGIN_ID
3172 where process_id = x(ctr)
3173 and end_date is null;
3174 elsif (p_mode = 'RC')
3175 then
3176 forall ctr in x.first .. x.last
3177 update amw_process
3178 set risk_count_latest = (select count(*) from (
3179 select distinct risk_id
3180 from amw_risk_associations
3181 where pk1 in ((select parent_child_id
3182 from amw_proc_hierarchy_denorm
3183 where process_id = x(ctr)
3184 and up_down_ind = 'D'
3185 and hierarchy_type = 'L') union all (select x(ctr) from dual) )
3186 and deletion_date is null
3187 and object_type = 'PROCESS'
3188 )),
3189
3190 control_count_latest = (select count(*) from
3191
3192 (select distinct control_id from amw_control_associations
3193 where pk1 in ((select parent_child_id
3194 from amw_proc_hierarchy_denorm
3195 where process_id = x(ctr)
3196 and up_down_ind = 'D'
3197 and hierarchy_type = 'L') union all (select x(ctr) from dual) )
3198 and deletion_date is null
3199 and object_type = 'RISK')),
3200 object_version_number = object_version_number + 1
3201 ,last_update_date = sysdate
3202 ,last_updated_by = G_USER_ID
3203 ,last_update_login = G_LOGIN_ID
3204 where process_id = x(ctr)
3205 and end_date is null;
3206
3207
3208
3209
3210 end if;
3211 end if;
3212
3213
3214 exception
3215
3216 when others
3217 then raise FND_API.G_EXC_UNEXPECTED_ERROR;
3218
3219 end update_all_latest_rc_counts;
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231 /* Update the org_counts for all approved processes in RL
3232 * Amit, in my opinion we need something that does it per process
3233 * rather than for everything -- pls, give this a thought
3234 */
3235 procedure update_all_org_counts
3236
3237 is
3238 cursor c is (select process_id from amw_process where
3239 approval_date is not null
3240 and approval_end_date is null
3241 and process_id <> -1);
3242 type t_n is table of number;
3243 x t_n;
3244 begin
3245 open c;
3246 fetch c bulk collect into x;
3247 close c;
3248
3249 if x.exists(1) then
3250 forall ctr in x.first .. x.last
3251 update amw_process
3252 set org_count = (select count(*) from
3253 (select distinct organization_id
3254 from amw_process_organization
3255 where process_id = x(ctr)
3256 and end_date is null
3257 and (deletion_date is null or (deletion_date is not null and approval_date is null)))),
3258 object_version_number = object_version_number + 1
3259 ,last_update_date = sysdate
3260 ,last_updated_by = G_USER_ID
3261 ,last_update_login = G_LOGIN_ID
3262 where process_id = x(ctr)
3263 and approval_date is not null
3264 and approval_end_date is null;
3265 end if;
3266
3267 end update_all_org_counts;
3268
3269
3270 /* update the org count for p_process_id */
3271 procedure update_org_count(p_process_id in number)
3272
3273 is
3274
3275 begin
3276 update amw_process
3277 set org_count = (select count(*) from
3278 (select distinct organization_id
3279 from amw_process_organization
3280 where process_id = p_process_id
3281 and end_date is null
3282 and (deletion_date is null or (deletion_date is not null and approval_date is null)))),
3283 object_version_number = object_version_number + 1
3284 ,last_update_date = sysdate
3285 ,last_updated_by = G_USER_ID
3286 ,last_update_login = G_LOGIN_ID
3287 where approval_date is not null
3288 and approval_end_date is null
3289 and process_id <> -1 --retained for safety
3290 and process_id = p_process_id;
3291
3292
3293 exception
3294
3295
3296 when others
3297 then raise FND_API.G_EXC_UNEXPECTED_ERROR;
3298
3299 end update_org_count;
3300
3301 -------------------------------------------------------------------------------------------
3302
3303
3304 /* the following is needed for ProcessRevisionAMImpl.java
3305 */
3306
3307 procedure update_attachments(p_old_prev_id in varchar2,
3308 p_new_prev_id in varchar2,
3309 x_return_status out nocopy varchar2,
3310 x_msg_count out nocopy number,
3311 x_msg_data out nocopy varchar2)
3312
3313 is
3314 l_api_name constant varchar2(30) := 'update_attachments';
3315
3316 p_init_msg_list varchar2(10) := FND_API.G_FALSE;
3317
3318 begin
3319 x_return_status := FND_API.G_RET_STS_SUCCESS;
3320 if FND_API.to_Boolean(p_init_msg_list) then
3321 FND_MSG_PUB.initialize;
3322 end if;
3323
3324 if FND_GLOBAL.user_id is null then
3325 AMW_Utility_PVT.Error_Message(p_message_name => 'USER_PROFILE_MISSING');
3326 raise FND_API.G_EXC_ERROR;
3327 end if;
3328
3329 --First remove all the old attachments
3330 FND_ATTACHED_DOCUMENTS2_PKG.delete_attachments(X_entity_name => 'AMW_PROCESS',
3331 X_pk1_value => p_old_prev_id);
3332
3333 --copy over all attachments of the temporary rev id
3334 fnd_attached_documents2_pkg.copy_attachments(
3335 X_from_entity_name => 'AMW_PROCESS',
3336 X_from_pk1_value => p_new_prev_id,
3337 X_to_entity_name => 'AMW_PROCESS',
3338 X_to_pk1_value => p_old_prev_id,
3339 X_created_by => g_user_id,
3340 X_last_update_login => g_login_id,
3341 X_program_id => FND_GLOBAL.CONC_PROGRAM_ID,
3342 X_request_id => FND_GLOBAL.conc_request_id);
3343
3344
3345 --remove all the attachments of the temporary id
3346
3347 FND_ATTACHED_DOCUMENTS2_PKG.delete_attachments(X_entity_name => 'AMW_PROCESS',
3348 X_pk1_value => p_new_prev_id);
3349
3350
3351 exception
3352 when OTHERS then
3353
3354 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
3355
3356 FND_MSG_PUB.Count_And_Get(p_encoded => FND_API.G_FALSE,
3357 p_count => x_msg_count,
3358 p_data => x_msg_data);
3359
3360 end update_attachments;
3361
3362 procedure create_new_process_as_child(
3363 p_parent_process_id in number,
3364 p_item_type in varchar2,
3365 p_display_name in varchar2,
3366 p_description in varchar2,
3367 p_control_type in varchar2,
3368 x_return_status out nocopy varchar2,
3369 x_msg_count out nocopy number,
3370 x_msg_data out nocopy varchar2) is
3371
3372 l_pid number;
3373 l_name number;
3374
3375 begin
3376
3377 select amw_process_name_s.nextval into l_name from dual;
3378
3379 l_pid := create_new_icm_process(
3380 p_name => to_char(l_name),
3381 p_item_type => p_item_type,
3382 p_display_name => p_display_name,
3383 p_description => p_description);
3384
3385 update amw_process
3386 set PROCESS_TYPE = decode(p_control_type, 'A', 'C', 'M', 'C', 'B', 'C', PROCESS_TYPE),
3387 CONTROL_ACTIVITY_TYPE = decode(p_control_type, '-1', CONTROL_ACTIVITY_TYPE, p_control_type)
3388 where process_id = l_pid
3389 and end_date is null;
3390
3391 add_existing_process_as_child(
3392 p_parent_process_id => p_parent_process_id,
3393 p_child_process_id => l_pid,
3394 x_return_status => x_return_status,
3395 x_msg_count => x_msg_count,
3396 x_msg_data => x_msg_data);
3397
3398 conv_tutor_grants(l_pid);
3399
3400 end create_new_process_as_child;
3401
3402
3403
3404 procedure conv_tutor_add_child(
3405 p_parent_process_id in number,
3406 p_display_name in varchar2,
3407 p_control_type in varchar2,
3408 x_return_status out nocopy varchar2,
3409 x_msg_count out nocopy number,
3410 x_msg_data out nocopy varchar2) is
3411
3412 l_pid number;
3413
3414 begin
3415
3416 select process_id
3417 into l_pid
3418 from AMW_LATEST_REVISIONS_V
3419 where display_name = p_display_name;
3420
3421 add_existing_process_as_child(
3422 p_parent_process_id => p_parent_process_id,
3423 p_child_process_id => l_pid,
3424 x_return_status => x_return_status,
3425 x_msg_count => x_msg_count,
3426 x_msg_data => x_msg_data);
3427
3428 conv_tutor_grants(l_pid);
3429
3430 exception
3431 when too_many_rows then
3432 fnd_message.set_name('AMW','AMW_COV_TUTOR_NONUNQ');
3433 fnd_message.set_token('AMW_COV_TUTOR_NONUNQ', p_display_name);
3434 x_msg_data := fnd_message.get;
3435 x_return_status := FND_API.G_RET_STS_ERROR;
3436
3437
3438 when no_data_found then
3439 create_new_process_as_child(
3440 p_parent_process_id => p_parent_process_id,
3441 p_item_type => 'AUDITMGR',
3442 p_display_name => p_display_name,
3443 p_description => p_display_name,
3444 p_control_type => p_control_type,
3445 x_return_status => x_return_status,
3446 x_msg_count => x_msg_count,
3447 x_msg_data => x_msg_data);
3448
3449 end conv_tutor_add_child;
3450
3451
3452 procedure conv_tutor_grants(l_process_id in number) is
3453
3454 l_return_status varchar2(10);
3455 l_msg_count number;
3456 l_msg_data varchar2(4000);
3457 l_party_id number;
3458
3459 begin
3460
3461 select person_party_id
3462 into l_party_id
3463 from fnd_user
3464 where user_id = G_USER_ID;
3465
3466 AMW_SECURITY_PUB.grant_role_guid
3467 (
3468 p_api_version => 1,
3469 p_role_name => 'AMW_RL_PROC_OWNER_ROLE',
3470 p_object_name => 'AMW_PROCESS_APPR_ETTY',
3471 p_instance_type => 'INSTANCE',
3472 p_instance_set_id => null,
3473 p_instance_pk1_value => l_process_id,
3474 p_instance_pk2_value => null,
3475 p_instance_pk3_value => null,
3476 p_instance_pk4_value => null,
3477 p_instance_pk5_value => null,
3478 p_party_id => l_party_id,
3479 p_start_date => g_sysdate,
3480 p_end_date => null,
3481 x_return_status => l_return_status,
3482 x_errorcode => l_msg_count,
3483 x_grant_guid => l_msg_data);
3484
3485 /* AMW_SECURITY_PUB.grant_role_guid
3486 (
3487 p_api_version => 1,
3488 p_role_name => 'AMW_RL_PROC_FINANCE_OWNER_ROLE',
3489 p_object_name => 'AMW_PROCESS_APPR_ETTY',
3490 p_instance_type => 'INSTANCE',
3491 p_instance_set_id => null,
3492 p_instance_pk1_value => l_process_id,
3493 p_instance_pk2_value => null,
3494 p_instance_pk3_value => null,
3495 p_instance_pk4_value => null,
3496 p_instance_pk5_value => null,
3497 p_party_id => l_party_id,
3498 p_start_date => g_sysdate,
3499 p_end_date => null,
3500 x_return_status => l_return_status,
3501 x_errorcode => l_msg_count,
3502 x_grant_guid => l_msg_data);
3503
3504 AMW_SECURITY_PUB.grant_role_guid
3505 (
3506 p_api_version => 1,
3507 p_role_name => 'AMW_RL_PROC_APPL_OWNER_ROLE',
3508 p_object_name => 'AMW_PROCESS_APPR_ETTY',
3509 p_instance_type => 'INSTANCE',
3510 p_instance_set_id => null,
3511 p_instance_pk1_value => l_process_id,
3512 p_instance_pk2_value => null,
3513 p_instance_pk3_value => null,
3514 p_instance_pk4_value => null,
3515 p_instance_pk5_value => null,
3516 p_party_id => l_party_id,
3517 p_start_date => g_sysdate,
3518 p_end_date => null,
3519 x_return_status => l_return_status,
3520 x_errorcode => l_msg_count,
3521 x_grant_guid => l_msg_data);
3522 */
3523
3524 end conv_tutor_grants;
3525
3526
3527
3528 procedure Check_Root_Access(p_predicate in varchar2,
3529 p_hasAccess out NOCOPY varchar2) is
3530
3531 l_hasaccess varchar2(1) := 'N';
3532 cursor_select INTEGER;
3533 cursor_execute INTEGER;
3534 query_to_exec VARCHAR2(32767);
3535
3536 begin
3537
3538 query_to_exec := 'select process_id from AMW_CURRENT_APPRVD_REV_V where process_id = -1 and '||p_predicate;
3539 cursor_select := DBMS_SQL.OPEN_CURSOR;
3540 DBMS_SQL.PARSE(cursor_select, query_to_exec, DBMS_SQL.NATIVE);
3541 cursor_execute := DBMS_SQL.EXECUTE(cursor_select);
3542 IF DBMS_SQL.FETCH_ROWS(cursor_select) > 0 THEN
3543 l_hasaccess := 'Y';
3544 ELSE
3545 l_hasaccess := 'N';
3546 END IF;
3547 DBMS_SQL.CLOSE_CURSOR(cursor_select);
3548
3549 p_hasAccess := l_hasAccess;
3550
3551 end Check_Root_Access;
3552
3553
3554
3555 PROCEDURE reset_count(
3556 errbuf out nocopy varchar2,
3557 retcode out nocopy varchar2
3558 ) IS
3559
3560 conc_status boolean;
3561
3562 BEGIN
3563 retcode :=0;
3564 errbuf :='';
3565
3566 --updates latest hier denorm
3567 amw_rl_hierarchy_pkg.update_denorm (-1, sysdate);
3568 --updates approved hier denorm
3569 amw_rl_hierarchy_pkg.update_approved_denorm (-1, sysdate);
3570
3571 update amw_process
3572 set risk_count = null,
3573 control_count = null,
3574 risk_count_latest = null,
3575 control_count_latest = null;
3576
3577 --updates latest risk/control counts
3578 amw_rl_hierarchy_pkg.update_all_latest_rc_counts('RC');
3579 --updates approved risk counts
3580 amw_rl_hierarchy_pkg.update_appr_risk_counts;
3581 --updates approved control counts
3582 amw_rl_hierarchy_pkg.update_appr_control_counts;
3583 -- update approved org counts
3584 amw_rl_hierarchy_pkg.update_all_org_counts;
3585
3586 commit;
3587
3588 EXCEPTION
3589
3590 WHEN OTHERS THEN
3591 rollback;
3592 retcode :=2;
3593 errbuf := SUBSTR(SQLERRM,1,1000);
3594 conc_status := FND_CONCURRENT.SET_COMPLETION_STATUS('ERROR','Error: '|| SQLERRM);
3595
3596 END reset_count;
3597
3598
3599 -- returns 1 if process is present in the latest hiearchy
3600 -- 0 otherwise
3601 function is_proc_in_ltst_hier(p_process_id in number) return number is
3602 ret_val number := 1;
3603 begin
3604 if p_process_id = -1 then
3605 return 1;
3606 else
3607 select 1 into ret_val
3608 from dual
3609 where (exists
3610 (select parent_id from amw_latest_hierarchies
3611 where parent_id = p_process_id
3612 and (organization_id = -1 or organization_id is null)))
3613 or (exists
3614 (select child_id from amw_latest_hierarchies
3615 where child_id = p_process_id
3616 and (organization_id = -1 or organization_id is null)));
3617
3618 return ret_val;
3619 end if;
3620 exception
3621 when no_data_found then
3622 ret_val := 0;
3623 return ret_val;
3624
3625 when too_many_rows then -- shouldn't happen... still
3626 ret_val := 1;
3627 return ret_val;
3628
3629 end is_proc_in_ltst_hier;
3630
3631 function areChildListSame(p_process_id in number) return varchar is
3632 retvalue varchar2(1);
3633 l_dummy number;
3634 begin
3635
3636 retvalue := 'N';
3637
3638 begin
3639 select child_id
3640 into l_dummy
3641 from amw_approved_hierarchies
3642 where parent_id = p_process_id
3643 and (organization_id is null or organization_id = -1)
3644 and (end_date is null or end_date > sysdate)
3645 and child_id not in
3646 (select child_id
3647 from amw_latest_hierarchies
3648 where parent_id = p_process_id
3649 and (organization_id is null or organization_id = -1));
3650 exception
3651 when no_data_found then
3652 begin
3653 select child_id
3654 into l_dummy
3655 from amw_latest_hierarchies
3656 where parent_id = p_process_id
3657 and (organization_id is null or organization_id = -1)
3658 and child_id not in
3659 (select child_id
3660 from amw_approved_hierarchies
3661 where parent_id = p_process_id
3662 and (organization_id is null or organization_id = -1)
3663 and (end_date is null or end_date > sysdate));
3664 exception
3665 when too_many_rows then
3666 return retvalue;
3667 when no_data_found then
3668 retvalue := 'Y';
3669 return retvalue;
3670 end;
3671 when too_many_rows then
3672 return retvalue;
3673 end;
3674 return retvalue;
3675 end;
3676
3677 function does_apprvd_ver_exst(p_process_id in number) return varchar is
3678 l_dummy number;
3679 begin
3680 select 1
3681 into l_dummy
3682 from amw_process
3683 where process_id = p_process_id
3684 and approval_status = 'A';
3685
3686 return 'Y';
3687
3688 exception
3689 when no_data_found then
3690 return 'N';
3691 when too_many_rows then
3692 return 'Y';
3693 end;
3694
3695 -- this api is to be called from java to figure out if the process
3696 -- is undoable or not. Based on this, the Undo buutton should
3697 -- be rendered
3698 procedure isProcessUndoAble ( p_process_id in number,
3699 ret_value out nocopy varchar2,
3700 x_return_status out nocopy varchar2,
3701 x_msg_count out nocopy number,
3702 x_msg_data out nocopy varchar2) is
3703
3704 l_api_name constant varchar2(30) := 'isProcessUndoAble';
3705 p_init_msg_list varchar2(10) := FND_API.G_FALSE;
3706 err_msg varchar2(4000);
3707 l_dummy number;
3708 appstatus varchar2(10);
3709
3710 begin
3711 x_return_status := FND_API.G_RET_STS_SUCCESS;
3712 IF FND_API.to_Boolean( p_init_msg_list ) THEN
3713 FND_MSG_PUB.initialize;
3714 END IF;
3715 IF FND_GLOBAL.User_Id IS NULL THEN
3716 AMW_Utility_PVT.Error_Message(p_message_name => 'USER_PROFILE_MISSING');
3717 RAISE FND_API.G_EXC_ERROR;
3718 END IF;
3719
3720 ret_value := 'N';
3721
3722 -- check if the process is draft
3723
3724 select approval_status into appstatus from amw_process
3725 where process_id = p_process_id and end_date is null;
3726
3727 if appstatus <> 'D' then
3728 return;
3729 end if;
3730
3731 -- check if the draft has been created due to addition/deletion of children
3732
3733 if areChildListSame(p_process_id) = 'Y' then
3734 ret_value := 'Y';
3735 return;
3736 else
3737 return;
3738 end if;
3739
3740 exception
3741 WHEN FND_API.G_EXC_ERROR THEN
3742 ROLLBACK;
3743 x_return_status := FND_API.G_RET_STS_ERROR;
3744 FND_MSG_PUB.Count_And_Get(p_encoded => FND_API.G_FALSE,
3745 p_count => x_msg_count,
3746 p_data => x_msg_data);
3747
3748 WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
3749 ROLLBACK;
3750 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
3751 FND_MSG_PUB.Count_And_Get(p_encoded => FND_API.G_FALSE,
3752 p_count => x_msg_count,
3753 p_data => x_msg_data);
3754
3755 WHEN OTHERS THEN
3756 ROLLBACK;
3757 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
3758 IF FND_MSG_PUB.Check_Msg_Level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR)
3759 THEN
3760 FND_MSG_PUB.Add_Exc_Msg(G_PKG_NAME,l_api_name);
3761 END IF;
3762 FND_MSG_PUB.Count_And_Get (p_encoded => FND_API.G_FALSE,
3763 p_count => x_msg_count,
3764 p_data => x_msg_data);
3765 end;
3766
3767 --========================================================================================================
3768 -- call this only after calling isProcessUndoAble.
3769 -- This api performs the delete (purging of draft row) action
3770 -- if conditions are satisfied
3771 procedure delete_draft (p_process_id in number,
3772 x_return_status out nocopy varchar2,
3773 x_msg_count out nocopy number,
3774 x_msg_data out nocopy varchar2) is
3775
3776 l_api_name constant varchar2(30) := 'delete_draft';
3777 p_init_msg_list varchar2(10) := FND_API.G_FALSE;
3778 err_msg varchar2(4000);
3779 appexst varchar2(1);
3780 l_risk_exists boolean :=false;
3781 l_control_exists boolean :=false;
3782 cursor parents(pid number) is
3783 select parent_id
3784 from amw_latest_hierarchies
3785 where child_id = pid
3786 and (organization_id is null or organization_id = -1);
3787 parent_rec parents%rowtype;
3788 l_flag varchar2(10);
3789 previd number;
3790 l_dummy number;
3791 ret_val varchar2(10);
3792
3793 begin
3794 x_return_status := FND_API.G_RET_STS_SUCCESS;
3795 IF FND_API.to_Boolean( p_init_msg_list ) THEN
3796 FND_MSG_PUB.initialize;
3797 END IF;
3798 IF FND_GLOBAL.User_Id IS NULL THEN
3799 AMW_Utility_PVT.Error_Message(p_message_name => 'USER_PROFILE_MISSING');
3800 RAISE FND_API.G_EXC_ERROR;
3801 END IF;
3802
3803
3804
3805 --ko we need this to be outside of IF block to delete the attachments.
3806 select process_rev_id
3807 into previd from amw_process
3808 where process_id = p_process_id
3809 and end_date is null;
3810
3811 appexst := does_apprvd_ver_exst(p_process_id);
3812 if appexst = 'Y' then
3813
3814 --ko moved this undoable check from outside of ifblock to inside..As a new draft can be deleted even if it is having children.
3815 -- do another check for undoablity
3816
3817 isProcessUndoAble ( p_process_id => p_process_id,
3818 ret_value => ret_val,
3819 x_return_status => x_return_status,
3820 x_msg_count => x_msg_count,
3821 x_msg_data => x_msg_data);
3822
3823 if ret_val <> 'Y' then
3824 fnd_message.set_name('AMW','AMW_CANT_UNDO_DRAFT');
3825 err_msg := fnd_message.get;
3826 fnd_msg_pub.add_exc_msg(p_pkg_name => 'amw_rl_hierarchy_pkg',
3827 p_procedure_name => 'delete_draft',
3828 p_error_text => err_msg);
3829 raise FND_API.G_EXC_ERROR;
3830 end if;
3831 if x_return_status <> FND_API.G_RET_STS_SUCCESS then
3832 raise FND_API.G_EXC_UNEXPECTED_ERROR;
3833 end if;
3834
3835
3836 delete from amw_process
3837 where process_id = p_process_id
3838 and end_date is null;
3839
3840 delete from amw_process_names_tl
3841 where process_rev_id = previd;
3842
3843 update amw_process
3844 set end_date = null
3845 where process_id = p_process_id
3846 and approval_date is not null
3847 and approval_end_date is null;
3848
3849 else -- appexst = 'N'
3850
3851 select standard_process_flag, process_rev_id
3852 into l_flag, previd from amw_process
3853 where process_id = p_process_id;
3854
3855 if l_flag = 'Y' then
3856 begin
3857 select 1 into l_dummy from dual
3858 where exists
3859 (select 1 from amw_process
3860 where standard_variation = previd
3861 and end_date is null);
3862
3863 fnd_message.set_name('AMW','AMW_CANT_DEL_DRAFT_NS');
3864 err_msg := fnd_message.get;
3865 fnd_msg_pub.add_exc_msg(p_pkg_name => 'amw_rl_hierarchy_pkg',
3866 p_procedure_name => 'delete_draft',
3867 p_error_text => err_msg);
3868 raise FND_API.G_EXC_ERROR;
3869
3870 exception
3871 when no_data_found then
3872 null;
3873 end;
3874 end if;
3875
3876 for parent_rec in parents(p_process_id) loop
3877 exit when parents%notfound;
3878 revise_process_if_necessary(parent_rec.parent_id);
3879 delete from amw_latest_hierarchies
3880 where parent_id = parent_rec.parent_id
3881 and child_id = p_process_id
3882 and (organization_id is null or organization_id = -1);
3883 end loop;
3884
3885 --kosriniv need to de link the children this process has..
3886 delete from amw_latest_hierarchies
3887 where parent_id = p_process_id
3888 and (organization_id is null or organization_id = -1);
3889 delete from amw_process where process_id = p_process_id;
3890 delete from amw_process_names_tl where process_rev_id = previd;
3891
3892 end if;
3893
3894 -- perform other common delete operations
3895
3896 delete from amw_risk_associations
3897 where pk1 = p_process_id
3898 and approval_date is null
3899 and object_type = 'PROCESS';
3900 --ko we need to update the latest risk & controls counts..
3901 IF SQL%FOUND THEN
3902 l_risk_exists := TRUE;
3903 END IF;
3904
3905 update amw_risk_associations
3906 set deletion_date = null
3907 where pk1 = p_process_id
3908 and object_type = 'PROCESS'
3909 and deletion_date is not null
3910 and deletion_approval_date is null;
3911
3912 IF SQL%FOUND THEN
3913 l_risk_exists := TRUE;
3914 END IF;
3915
3916 delete from amw_control_associations
3917 where pk1 = p_process_id
3918 and approval_date is null
3919 and object_type = 'RISK';
3920
3921 IF SQL%FOUND THEN
3922 l_control_exists := TRUE;
3923 END IF;
3924
3925 update amw_control_associations
3926 set deletion_date = null
3927 where pk1 = p_process_id
3928 and object_type = 'RISK'
3929 and deletion_date is not null
3930 and deletion_approval_date is null;
3931
3932 IF SQL%FOUND THEN
3933 l_control_exists := TRUE;
3934 END IF;
3935
3936 delete from amw_acct_associations
3937 where pk1 = p_process_id
3938 and approval_date is null
3939 and object_type = 'PROCESS';
3940
3941 update amw_acct_associations
3942 set deletion_date = null
3943 where pk1 = p_process_id
3944 and object_type = 'PROCESS'
3945 and deletion_date is not null
3946 and deletion_approval_date is null;
3947
3948
3949 delete from amw_objective_associations
3950 where pk1 = p_process_id
3951 and approval_date is null
3952 and object_type in ('PROCESS', 'CONTROL');
3953
3954 update amw_objective_associations
3955 set deletion_date = null
3956 where pk1 = p_process_id
3957 and object_type in ('PROCESS', 'CONTROL')
3958 and deletion_date is not null
3959 and deletion_approval_date is null;
3960
3961
3962 delete from amw_significant_elements
3963 where pk1 = p_process_id
3964 and approval_date is null
3965 and object_type = 'PROCESS';
3966
3967 update amw_significant_elements
3968 set deletion_date = null
3969 where pk1 = p_process_id
3970 and object_type = 'PROCESS'
3971 and deletion_date is not null
3972 and deletion_approval_date is null;
3973
3974
3975 FND_ATTACHED_DOCUMENTS2_PKG.delete_attachments(X_entity_name => 'AMW_PROCESS',
3976 X_pk1_value => previd);
3977
3978 -- cancel existing change requests
3979
3980 -- update latest hierarchy denorm
3981 amw_rl_hierarchy_pkg.update_denorm (-1, sysdate);
3982
3983 --ko update the risk control counts..
3984
3985 if appexst = 'Y' AND l_risk_exists then
3986
3987 -- Update the latest risk control counts..
3988 update_latest_risk_counts(p_process_id);
3989 end if;
3990
3991 if appexst = 'Y' AND l_control_exists then
3992
3993 update_latest_control_counts(p_process_id);
3994
3995 end if;
3996
3997 exception
3998 WHEN FND_API.G_EXC_ERROR THEN
3999 ROLLBACK;
4000 x_return_status := FND_API.G_RET_STS_ERROR;
4001 FND_MSG_PUB.Count_And_Get(p_encoded => FND_API.G_FALSE,
4002 p_count => x_msg_count,
4003 p_data => x_msg_data);
4004
4005 WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
4006 ROLLBACK;
4007 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
4008 FND_MSG_PUB.Count_And_Get(p_encoded => FND_API.G_FALSE,
4009 p_count => x_msg_count,
4010 p_data => x_msg_data);
4011
4012 WHEN OTHERS THEN
4013 ROLLBACK;
4014 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
4015 IF FND_MSG_PUB.Check_Msg_Level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR)
4016 THEN
4017 FND_MSG_PUB.Add_Exc_Msg(G_PKG_NAME,l_api_name);
4018 END IF;
4019 FND_MSG_PUB.Count_And_Get (p_encoded => FND_API.G_FALSE,
4020 p_count => x_msg_count,
4021 p_data => x_msg_data);
4022 end;
4023
4024
4025 --========================================================================================================
4026 -- call this in the create process from UI page..
4027 -- This api gives the user process owner grant..
4028 -- if conditions are satisfied
4029 procedure create_process_owner_grant (p_process_id in varchar2,
4030 x_return_status out nocopy varchar2,
4031 x_msg_count out nocopy number,
4032 x_msg_data out nocopy varchar2) is
4033
4034 l_api_name constant varchar2(30) := 'create_process_owner_grant';
4035 p_init_msg_list varchar2(10) := FND_API.G_FALSE;
4036 err_msg varchar2(4000);
4037 l_party_id number;
4038
4039 begin
4040
4041 --always initialize global variables in th api's used from SelfSerivice Fwk..
4042 G_USER_ID := FND_GLOBAL.USER_ID;
4043 G_LOGIN_ID := FND_GLOBAL.CONC_LOGIN_ID;
4044 x_return_status := FND_API.G_RET_STS_SUCCESS;
4045 IF FND_API.to_Boolean( p_init_msg_list ) THEN
4046 FND_MSG_PUB.initialize;
4047 END IF;
4048 IF FND_GLOBAL.User_Id IS NULL THEN
4049 AMW_Utility_PVT.Error_Message(p_message_name => 'USER_PROFILE_MISSING');
4050 RAISE FND_API.G_EXC_ERROR;
4051 END IF;
4052
4053 select person_party_id
4054 into l_party_id
4055 from fnd_user
4056 where user_id = G_USER_ID;
4057
4058 AMW_SECURITY_PUB.grant_role_guid
4059 (
4060 p_api_version => 1,
4061 p_role_name => 'AMW_RL_PROC_OWNER_ROLE',
4062 p_object_name => 'AMW_PROCESS_APPR_ETTY',
4063 p_instance_type => 'INSTANCE',
4064 p_instance_set_id => null,
4065 p_instance_pk1_value => p_process_id,
4066 p_instance_pk2_value => null,
4067 p_instance_pk3_value => null,
4068 p_instance_pk4_value => null,
4069 p_instance_pk5_value => null,
4070 p_party_id => l_party_id,
4071 p_start_date => g_sysdate,
4072 p_end_date => null,
4073 x_return_status =>x_return_status,
4074 x_errorcode => x_msg_count,
4075 x_grant_guid => x_msg_data);
4076
4077
4078
4079 exception
4080 WHEN FND_API.G_EXC_ERROR THEN
4081 ROLLBACK;
4082 x_return_status := FND_API.G_RET_STS_ERROR;
4083 FND_MSG_PUB.Count_And_Get(p_encoded => FND_API.G_FALSE,
4084 p_count => x_msg_count,
4085 p_data => x_msg_data);
4086
4087 WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
4088 ROLLBACK;
4089 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
4090 FND_MSG_PUB.Count_And_Get(p_encoded => FND_API.G_FALSE,
4091 p_count => x_msg_count,
4092 p_data => x_msg_data);
4093
4094 WHEN OTHERS THEN
4095 ROLLBACK;
4096 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
4097 IF FND_MSG_PUB.Check_Msg_Level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR)
4098 THEN
4099 FND_MSG_PUB.Add_Exc_Msg(G_PKG_NAME,l_api_name);
4100 END IF;
4101 FND_MSG_PUB.Count_And_Get (p_encoded => FND_API.G_FALSE,
4102 p_count => x_msg_count,
4103 p_data => x_msg_data);
4104 end create_process_owner_grant;
4105
4106 -- *******************************************************--
4107
4108 procedure delete_activities(p_parent_process_id in number,
4109 p_child_id_string in varchar2,
4110 x_return_status out nocopy varchar2,
4111 x_msg_count out nocopy number,
4112 x_msg_data out nocopy varchar2)
4113 is
4114 l_api_name constant varchar2(30) := 'delete_activities';
4115 p_init_msg_list varchar2(10) := FND_API.G_TRUE;
4116 str varchar2(4000);
4117 diff number;
4118 childstr varchar2(100);
4119 l_child_string varchar2(4000);
4120 l_child_id number;
4121
4122 begin
4123 x_return_status := FND_API.G_RET_STS_SUCCESS;
4124 IF FND_API.to_Boolean( p_init_msg_list ) THEN
4125 FND_MSG_PUB.initialize;
4126 END IF;
4127 IF FND_GLOBAL.User_Id IS NULL THEN
4128 AMW_Utility_PVT.Error_Message(p_message_name => 'USER_PROFILE_MISSING');
4129 RAISE FND_API.G_EXC_ERROR;
4130 END IF;
4131
4132 l_child_string := p_child_id_string;
4133 while LENGTH(l_child_string) <> 0 loop
4134 select LTRIM(l_child_string, '1234567890') into str from dual;
4135 diff := LENGTH(l_child_string) - LENGTH(str);
4136 if LENGTH(str) is null then
4137 diff := LENGTH(l_child_string);
4138 end if;
4139 select SUBSTR(l_child_string, 1, diff) into childstr from dual;
4140 l_child_id := to_number(childstr);
4141 delete from amw_latest_hierarchies where parent_id = p_parent_process_id
4142 and child_id = l_child_id and organization_id = -1;
4143 select LTRIM(str, 'x') into l_child_string from dual;
4144 end loop;
4145 exception
4146 WHEN FND_API.G_EXC_ERROR THEN
4147 ROLLBACK;
4148 x_return_status := FND_API.G_RET_STS_ERROR;
4149 FND_MSG_PUB.Count_And_Get(p_encoded => FND_API.G_FALSE,p_count => x_msg_count,p_data => x_msg_data);
4150
4151 WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
4152 ROLLBACK;
4153 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
4154 FND_MSG_PUB.Count_And_Get(p_encoded => FND_API.G_FALSE,p_count => x_msg_count,p_data => x_msg_data);
4155
4156 WHEN OTHERS THEN
4157 ROLLBACK;
4158 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
4159 IF FND_MSG_PUB.Check_Msg_Level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR)
4160 THEN
4161 FND_MSG_PUB.Add_Exc_Msg(G_PKG_NAME,l_api_name);
4162 END IF;
4163 FND_MSG_PUB.Count_And_Get (p_encoded => FND_API.G_FALSE,p_count => x_msg_count, p_data => x_msg_data);
4164
4165 end delete_activities;
4166
4167
4168 --The parent process and the child process both exist as ICM processes
4169 procedure add_activities( p_parent_process_id in number,
4170 p_child_id_string in varchar2,
4171 p_sysdate in Date default sysdate,
4172 x_return_status out nocopy varchar2,
4173 x_msg_count out nocopy number,
4174 x_msg_data out nocopy varchar2)
4175 is
4176 l_api_name constant varchar2(30) := 'add_activities';
4177 l_dummy pls_integer;
4178 l_approval_status amw_process.approval_status%type;
4179 l_child_order_number amw_latest_hierarchies.child_order_number%type;
4180 p_init_msg_list varchar2(10) := FND_API.G_TRUE;
4181 str varchar2(4000);
4182 diff number;
4183 childstr varchar2(100);
4184 l_child_string varchar2(4000);
4185 l_child_id number;
4186
4187 begin
4188 x_return_status := FND_API.G_RET_STS_SUCCESS;
4189 IF FND_API.to_Boolean( p_init_msg_list ) THEN
4190 FND_MSG_PUB.initialize;
4191 END IF;
4192 if FND_GLOBAL.user_id is null then
4193 AMW_Utility_PVT.Error_Message(p_message_name => 'USER_PROFILE_MISSING');
4194 raise FND_API.G_EXC_ERROR;
4195 end if;
4196
4197 --check if parent_process_id is null
4198 if p_parent_process_id is null then
4199 raise FND_API.G_EXC_ERROR;
4200 end if;
4201
4202 --check if parent process is locked
4203 if (is_locked_process(p_parent_process_id))
4204 then
4205 raise amw_process_locked_exception;
4206 end if;
4207
4208 l_child_string := p_child_id_string;
4209 while LENGTH(l_child_string) <> 0 loop
4210 select LTRIM(l_child_string, '1234567890') into str from dual;
4211 diff := LENGTH(l_child_string) - LENGTH(str);
4212 if LENGTH(str) is null then
4213 diff := LENGTH(l_child_string);
4214 end if;
4215 select SUBSTR(l_child_string, 1, diff) into childstr from dual;
4216 l_child_id := to_number(childstr);
4217 /* check if the child is an ancestor of parent already
4218 * so that a circular hierarchy cannot be created
4219 */
4220 if(is_ancestor_in_hierarchy(l_child_id,p_parent_process_id))
4221 then
4222 raise amw_circularity_exception;
4223 end if;
4224
4225 --we now check if this link is already existing in the latest hierarchy
4226
4227 open c_link_exist(p_parent_process_id,l_child_id);
4228 fetch c_link_exist into l_dummy;
4229 if(c_link_exist%found)
4230 then
4231 close c_link_exist;
4232 return;
4233 end if;
4234 close c_link_exist;
4235
4236
4237 --update the latest hierarchy table
4238 insert into amw_latest_hierarchies(ORGANIZATION_ID,
4239 PARENT_ID,
4240 CHILD_ID,
4241 CHILD_ORDER_NUMBER,
4242 LAST_UPDATE_DATE,
4243 LAST_UPDATED_BY,
4244 LAST_UPDATE_LOGIN,
4245 CREATION_DATE,
4246 CREATED_BY,
4247 OBJECT_VERSION_NUMBER
4248 )
4249 VALUES (-1,
4250 p_parent_process_id,
4251 l_child_id,
4252 AMW_CHILD_ORDER_S.nextval,
4253 p_sysdate,
4254 g_user_id,
4255 g_login_id,
4256 p_sysdate,
4257 g_user_id,
4258 1)
4259 returning CHILD_ORDER_NUMBER
4260 into l_child_order_number;
4261
4262
4263 update_appr_ch_ord_num_if_reqd(-1, p_parent_process_id, l_child_id,
4264 l_child_order_number);
4265
4266
4267 select LTRIM(str, 'x') into l_child_string from dual;
4268 end loop;
4269
4270 exception
4271 when FND_API.G_EXC_ERROR then
4272 ROLLBACK;
4273 x_return_status := FND_API.G_RET_STS_ERROR;
4274 FND_MSG_PUB.Count_And_Get(p_encoded => FND_API.G_FALSE,
4275 p_count => x_msg_count,
4276 p_data => x_msg_data);
4277 when FND_API.G_EXC_UNEXPECTED_ERROR then
4278 ROLLBACK;
4279 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
4280 FND_MSG_PUB.Count_And_Get(p_encoded => FND_API.G_FALSE,
4281 p_count => x_msg_count,
4282 p_data => x_msg_data);
4283 when amw_process_locked_exception then
4284 x_return_status := FND_API.G_RET_STS_ERROR;
4285 x_msg_count := x_msg_count + 1;
4286 fnd_message.set_name('AMW','AMW_PROCESS_LOCKED');
4287 x_msg_data := fnd_message.get;
4288 fnd_msg_pub.add_exc_msg(p_pkg_name => G_PKG_NAME,
4289 p_procedure_name => l_api_name,
4290 p_error_text => x_msg_data);
4291 raise FND_API.G_EXC_ERROR;
4292 when amw_circularity_exception then
4293 x_return_status := FND_API.G_RET_STS_ERROR;
4294 fnd_message.set_name('AMW','AMW_CIRCULARITY_CREATION');
4295 x_msg_count := x_msg_count + 1;
4296 x_msg_data := fnd_message.get;
4297 fnd_msg_pub.add_exc_msg(p_pkg_name => G_PKG_NAME,
4298 p_procedure_name => l_api_name,
4299 p_error_text => x_msg_count);
4300 raise FND_API.G_EXC_ERROR;
4301 when amw_processing_exception then
4302 ROLLBACK;
4303 x_return_status := FND_API.G_RET_STS_ERROR;
4304 FND_MSG_PUB.Count_And_Get(p_encoded => FND_API.G_FALSE,
4305 p_count => x_msg_count,
4306 p_data => x_msg_data);
4307 when OTHERS then
4308 ROLLBACK;
4309 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
4310 FND_MSG_PUB.Count_And_Get(p_encoded => FND_API.G_FALSE,
4311 p_count => x_msg_count,
4312 p_data => x_msg_data);
4313
4314 end add_activities;
4315
4316 procedure revise_process(p_process_id in number,
4317 p_init_msg_list IN VARCHAR2 := FND_API.G_FALSE,
4318 x_return_status out nocopy varchar2,
4319 x_msg_count out nocopy number,
4320 x_msg_data out nocopy varchar2)
4321 is
4322 begin
4323 G_USER_ID := FND_GLOBAL.USER_ID;
4324 G_LOGIN_ID := FND_GLOBAL.CONC_LOGIN_ID;
4325 x_return_status := FND_API.G_RET_STS_SUCCESS;
4326 IF FND_API.to_Boolean( p_init_msg_list ) THEN
4327 FND_MSG_PUB.initialize;
4328 END IF;
4329 IF FND_GLOBAL.User_Id IS NULL THEN
4330 AMW_Utility_PVT.Error_Message(p_message_name => 'USER_PROFILE_MISSING');
4331 RAISE FND_API.G_EXC_ERROR;
4332 END IF;
4333
4334 revise_process_if_necessary(p_process_id => p_process_id);
4335
4336 exception
4337 when OTHERS then
4338 ROLLBACK;
4339 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
4340 FND_MSG_PUB.Count_And_Get(p_encoded => FND_API.G_FALSE,
4341 p_count => x_msg_count,
4342 p_data => x_msg_data);
4343 end revise_process;
4344
4345 PROCEDURE update_latest_denorm_counts
4346 ( p_process_id IN NUMBER,
4347 p_commit IN VARCHAR2 := FND_API.G_FALSE,
4348 p_validation_level IN NUMBER := FND_API.G_VALID_LEVEL_FULL,
4349 p_init_msg_list IN VARCHAR2 := FND_API.G_FALSE,
4350 x_return_status OUT NOCOPY VARCHAR2,
4351 x_msg_count OUT NOCOPY VARCHAR2,
4352 x_msg_data OUT NOCOPY VARCHAR2)
4353 IS
4354
4355 L_API_NAME CONSTANT VARCHAR2(30) := 'update_latest_denorm_counts';
4356
4357
4358 BEGIN
4359
4360 --always initialize global variables in th api's used from SelfSerivice Fwk..
4361 G_USER_ID := FND_GLOBAL.USER_ID;
4362 G_LOGIN_ID := FND_GLOBAL.CONC_LOGIN_ID;
4363 x_return_status := FND_API.G_RET_STS_SUCCESS;
4364 IF FND_API.to_Boolean( p_init_msg_list ) THEN
4365 FND_MSG_PUB.initialize;
4366 END IF;
4367 IF FND_GLOBAL.User_Id IS NULL THEN
4368 AMW_Utility_PVT.Error_Message(p_message_name => 'USER_PROFILE_MISSING');
4369 RAISE FND_API.G_EXC_ERROR;
4370 END IF;
4371
4372 -- update the latest denorm hierarchy..
4373 AMW_RL_HIERARCHY_PKG.update_denorm(p_org_id => -1);
4374 -- Update the Risk Counts..
4375 update_latest_risk_counts(p_process_id => p_process_id);
4376 -- Update the Control Counts..
4377 update_latest_control_counts( p_process_id => p_process_id);
4378
4379
4380 exception
4381 WHEN FND_API.G_EXC_ERROR THEN
4382 ROLLBACK;
4383 x_return_status := FND_API.G_RET_STS_ERROR;
4384 FND_MSG_PUB.Count_And_Get(p_encoded => FND_API.G_FALSE,p_count => x_msg_count,p_data => x_msg_data);
4385
4386 WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
4387 ROLLBACK;
4388 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
4389 FND_MSG_PUB.Count_And_Get(p_encoded => FND_API.G_FALSE,p_count => x_msg_count,p_data => x_msg_data);
4390
4391 WHEN OTHERS THEN
4392 ROLLBACK;
4393 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
4394 IF FND_MSG_PUB.Check_Msg_Level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR)
4395 THEN
4396 FND_MSG_PUB.Add_Exc_Msg(G_PKG_NAME,l_api_name);
4397 END IF;
4398 FND_MSG_PUB.Count_And_Get (p_encoded => FND_API.G_FALSE,p_count => x_msg_count,p_data => x_msg_data);
4399 END update_latest_denorm_counts;
4400
4401 end AMW_RL_HIERARCHY_PKG;