DBA Data[Home] [Help]

PACKAGE BODY: APPS.FF_DATA_DICT

Source


1 PACKAGE body ff_data_dict AS
2 /* $Header: peffdict.pkb 120.4.12000000.2 2007/02/08 11:18:04 divicker ship $ */
3 --****************************************************************************
4 -- INSTALLATION PROCEDURE FOR : FF_CONTEXTS_F
5 --****************************************************************************
6 
7 procedure disable_ffuebru_trig is
8   statem varchar2(256);
9   sql_cur number;
10   ignore number;
11 begin
12   statem := 'alter trigger ff_user_entities_bru disable';
13   sql_cur := dbms_sql.open_cursor;
14   dbms_sql.parse(sql_cur,
15                  statem,
16                  dbms_sql.v7);
17   ignore := dbms_sql.execute(sql_cur);
18   dbms_sql.close_cursor(sql_cur);
19 end;
20 
21 procedure enable_ffuebru_trig is
22   statem varchar2(256);
23   sql_cur number;
24   ignore number;
25 begin
26   statem := 'alter trigger ff_user_entities_bru enable';
27   sql_cur := dbms_sql.open_cursor;
28   dbms_sql.parse(sql_cur,
29                  statem,
30                  dbms_sql.v7);
31   ignore := dbms_sql.execute(sql_cur);
32   dbms_sql.close_cursor(sql_cur);
33 end;
34 
35 procedure dis_cont_calc_trigger is
36   statem varchar2(256);
37   sql_cur number;
38   ignore number;
39 begin
40   statem := 'alter trigger FFGLOBALSF_9501D_DYT disable';
41   sql_cur := dbms_sql.open_cursor;
42   dbms_sql.parse(sql_cur,
43                  statem,
44                  dbms_sql.v7);
45   ignore := dbms_sql.execute(sql_cur);
46   dbms_sql.close_cursor(sql_cur);
47   statem := 'alter trigger FFGLOBALSF_9502I_DYT disable';
48   sql_cur := dbms_sql.open_cursor;
49   dbms_sql.parse(sql_cur,
50                  statem,
51                  dbms_sql.v7);
52   ignore := dbms_sql.execute(sql_cur);
53   dbms_sql.close_cursor(sql_cur);
54   statem := 'alter trigger FFGLOBALSF_9503U_DYT disable';
55   sql_cur := dbms_sql.open_cursor;
56   dbms_sql.parse(sql_cur,
57                  statem,
58                  dbms_sql.v7);
59   ignore := dbms_sql.execute(sql_cur);
60   dbms_sql.close_cursor(sql_cur);
61 end;
62 
63 procedure ena_cont_calc_trigger is
64   statem varchar2(256);
65   sql_cur number;
66   ignore number;
67 begin
68   statem := 'alter trigger FFGLOBALSF_9501D_DYT enable';
69   sql_cur := dbms_sql.open_cursor;
70   dbms_sql.parse(sql_cur,
71                  statem,
72                  dbms_sql.v7);
73   ignore := dbms_sql.execute(sql_cur);
74   dbms_sql.close_cursor(sql_cur);
75   statem := 'alter trigger FFGLOBALSF_9502I_DYT enable';
76   sql_cur := dbms_sql.open_cursor;
77   dbms_sql.parse(sql_cur,
78                  statem,
79                  dbms_sql.v7);
80   ignore := dbms_sql.execute(sql_cur);
81   dbms_sql.close_cursor(sql_cur);
82   statem := 'alter trigger FFGLOBALSF_9503U_DYT enable';
83   sql_cur := dbms_sql.open_cursor;
84   dbms_sql.parse(sql_cur,
85                  statem,
86                  dbms_sql.v7);
87   ignore := dbms_sql.execute(sql_cur);
88   dbms_sql.close_cursor(sql_cur);
89 end;
90 
91 
92 PROCEDURE install_ffc (p_phase IN number)
93 -----------------------------------------
94 IS
95     -- Install delivered formula contexts into the live tables. This delivery
96     -- procedure maintains referential integrity with all children of formula
97     -- contetxs. It must be executed before any other formula dictionary
98     -- routine.
99 
100     l_null_return varchar2(1); 		-- for 'select null' statements
101     l_new_surrogate_key number(15);     -- new surrogate key for delivery row
102 
103     CURSOR stu  			-- selects all rows from startup entity
104     IS
105         select context_name c_true_key
106 	,      rowid
107 	,      context_level
108 	,      data_type
109 	,      context_id c_surrogate_key
110 	from   hr_s_contexts;
111 
112 
113     stu_rec stu%ROWTYPE;		-- Record for above SELECT
114 
115     PROCEDURE crt_exc (exception_type IN varchar2)
116     ----------------------------------------------
117     IS
118 	-- Reports any exceptions during the delivery of startup data to
119 	-- FF_CONTEXTS_F
120     BEGIN
121 	-- When the installation procedures encounter an error that cannot
122 	-- be handled, an exception is raised and all work is rolled back
123 	-- to the last savepoint. The installation process then continues
124 	-- with the next primary key to install. The same exception will
125 	-- not be raised more than once.
126 
127 	rollback to new_context_name;
128 
129 	hr_legislation.insert_hr_stu_exceptions('ff_contexts'
130         ,      stu_rec.c_surrogate_key
131         ,      exception_type
132         ,      stu_rec.c_true_key);
133 
134 
135     END crt_exc;
136 
137     PROCEDURE check_next_sequence
138     -----------------------------
139     IS
140 
141 	v_sequence_number number(9);
142 	v_min_delivered number(9);
143 	v_max_delivered number(9);
144 
145 	-- Surrogate id conflicts may arise from two scenario's:
146 	-- 1. Where the newly select sequence value conflicts with values
147 	--    in the STU tables.
148 	-- 2. Where selected surrogate keys, from the installed tables,
149 	--    conflict with other rows in the STU tables.
150 	--
151 	-- Both of the above scenario's are tested for.
152 	-- The first is a simple match, where if a value is detected in the
153 	-- STU tables and the installed tables then a conflict is detected. In
154 	-- This instance all STU surrogate keys, for this table, are updated.
155 	-- The second is tested for using the sequences.
156 	-- If the next value from the live sequence is within the range of
157 	-- delivered surrogate id's then the live sequence must be incremented.
158 	-- If no action is taken, then duplicates may be introduced into the
159 	-- delivered tables, and child rows may be totally invalidated.
160 
161     BEGIN
162 
163 
164 	BEGIN	--check that the installde routes will not conflict
165 		--with the delivered values
166 
167 
168 	    select distinct null
169 	    into   l_null_return
170 	    from   ff_contexts a
171 	    where  exists
172 		(select null
173 		 from   hr_s_contexts b
174 		 where  a.context_id = b.context_id
175 		);
176 
177 	    --conflict may exist
178 	    --update all context_id's to remove conflict
179 
180 	    update /*+NO_INDEX*/ hr_s_contexts
181 	    set    context_id = context_id - 50000000;
182 
183 	    update /*+NO_INDEX*/ hr_s_route_context_usages
184             set    context_id = context_id - 50000000;
185 
186 	    update /*+NO_INDEX*/ hr_s_ftype_context_usages
187             set    context_id = context_id - 50000000;
188 
189 	    update /*+NO_INDEX*/ hr_s_function_context_usages
190             set    context_id = context_id - 50000000;
191 
192 	    update hr_s_application_ownerships
193 	    set    key_value = key_value - 50000000
194 	    where  key_name = 'CONTEXT_ID';
195 
196 	EXCEPTION WHEN NO_DATA_FOUND THEN NULL;
197 
198 	END; --check of context_id
199 
200 
201 
202 	select min(context_id) - (count(*) *3)
203 	,      max(context_id) + (count(*) *3)
204 	into   v_min_delivered
205 	,      v_max_delivered
206 	from   hr_s_contexts;
207 
208 	select ff_contexts_s.nextval
209 	into   v_sequence_number
210 	from   dual;
211 
212         IF v_sequence_number
213 	  BETWEEN v_min_delivered AND v_max_delivered THEN
214 
215             hr_legislation.munge_sequence('FF_CONTEXTS_S',
216                                           v_sequence_number,
217                                           v_max_delivered);
218 
219         END IF;
220 
221     END check_next_sequence;
222 
223     PROCEDURE update_uid
224     --------------------
225     IS
226 	-- Subprogram to update surrogate UID and all occurrences in child rows
227 
228         r_count NUMBER;
229 
230     BEGIN
231 
232 
233         BEGIN
234 
235 	    select distinct context_id
236             into   l_new_surrogate_key
237 	    from   ff_contexts
238 	    where  context_name = stu_rec.c_true_key;
239 
240         EXCEPTION WHEN NO_DATA_FOUND THEN
241 
242 
243 	    select ff_contexts_s.nextval
244 	    into   l_new_surrogate_key
245 	    from   dual;
246 
247         END;
248 
249 	-- Update all child entities
250 
251         update hr_s_contexts
252         set    context_id = l_new_surrogate_key
253         where  context_id = stu_rec.c_surrogate_key;
254 
255         update hr_s_application_ownerships
256         set    key_value = to_char(l_new_surrogate_key)
257         where  key_value = to_char(stu_rec.c_surrogate_key)
258         and    key_name = 'CONTEXT_ID';
259 
260         update hr_s_ftype_context_usages
261         set    context_id = l_new_surrogate_key
262         where  context_id = stu_rec.c_surrogate_key;
263 
264         update hr_s_route_context_usages
265         set    context_id = l_new_surrogate_key
266         where  context_id = stu_rec.c_surrogate_key;
267 
268         update hr_s_function_context_usages
269         set    context_id = l_new_surrogate_key
270         where  context_id = stu_rec.c_surrogate_key;
271 
272     END update_uid;
273 
274     PROCEDURE remove
275     ----------------
276     IS
277         -- Remove a row from the startup/delivered tables
278 
279     BEGIN
280 
281         delete from hr_s_contexts
282         where  rowid = stu_rec.rowid;
283 
284 
285         IF p_phase = 2 THEN
286 	    l_new_surrogate_key := stu_rec.c_surrogate_key;
287         END IF;
288 
289         delete from hr_stu_exceptions
290         where  surrogate_id = stu_rec.c_surrogate_key
291         and    table_name = 'FF_CONTEXTS';
292 
293      END remove;
294 
295     FUNCTION valid_ownership RETURN BOOLEAN
296     ---------------------------------------
297     IS
298 	-- Test ownership of this current row
299 
300     BEGIN
301 	-- This routine only operates in phase 1. Rows are present in the
302 	-- table hr_application_ownerships in the delivery account, which
303 	-- dictate which products a piece of data is used for. If the query
304 	-- returns a row, then this data is required, and the function will
305 	-- return true. If no rows are returned and an exception is raised,
306 	-- then this row is not required and may be deleted from the delivery
307 	-- tables.
308 
309 	-- If legislation code and subgroup code are included on the delivery
310 	-- tables, a check must be made to determine if the data is defined for
311 	-- a specific subgroup. If so the subgroup must be 'A'ctive for this
312 	-- installation.
313 
314 	-- A return code of TRUE indicates that the row is required.
315 
316 	-- The exception is raised within this procedure if no rows are returned
317 	-- in this select statement. If no rows are returned then one of the
318 	-- following is true:
319 	--     1. No ownership parameters are defined.
320 	--     2. The products, for which owning parameters are defined, are not
321 	--        installed with as status of 'I'.
322 	--     3. The data is defined for a legislation subgroup that is not active.
323 
324         IF p_phase <> 1 THEN	--only perform in phase 1
325 	    return TRUE;
326         END IF;
327 
328         select null --if exception raised then this row is not needed
329         into   l_null_return
330         from   dual
331         where  exists (
332                select null
333 	       from   hr_s_application_ownerships a
334 	       ,      fnd_product_installations b
335 	       ,      fnd_application c
336 	       where  a.key_name = 'CONTEXT_ID'
337 	       and    a.key_value = l_new_surrogate_key
338 	       and    a.product_name = c.application_short_name
339 	       and    c.application_id = b.application_id
340 	       and    ((b.status = 'I' and c.application_short_name <> 'PQP')
341 	              or
342                       (b.status in ('I', 'S') and c.application_short_name = 'PQP')));
343 
344         return TRUE;	--indicates row is required
345 
346     EXCEPTION WHEN NO_DATA_FOUND THEN
347 
348 	-- Row not needed for any installed product
349 
350 	remove;
351 
352 	return FALSE;	--indicates row not needed
353 
354     END valid_ownership;
355 
356     PROCEDURE transfer_row
357     ----------------------
358     IS
359 	-- Check if a delivered row is needed and insert into the
360 	-- live tables if it is.
361 
362     BEGIN
363 
364 	-- A simplistic installation. If the context name already exists
365 	-- in the live tables then no exception is raised and the row is
366 	-- delete from the delivery tables. If the context name does not
367 	-- exist then an exception is raised. The actual insert only occurs
368 	-- in phase 2 and after the insert has been performed the delivered
369 	-- row must be deleted.
370 
371         select null
372         into   l_null_return
373         from   ff_contexts
374         where  context_name = stu_rec.c_true_key;
375 
376 
377 	-- Row not required so delete
378 
379 	remove;
380 
381     EXCEPTION WHEN NO_DATA_FOUND THEN
382 
383 	-- Row not present in installed tables
384 
385 
386 	-- No inserts in phase 1
387 
388 	IF p_phase = 1 THEN
389 	    return;
390 	END IF;
391 
392         BEGIN
393 	insert into ff_contexts
394 	(context_id
395 	,context_level
396 	,context_name
397 	,data_type
398 	)
399 	values
400 	(stu_rec.c_surrogate_key
401 	,stu_rec.context_level
402 	,stu_rec.c_true_key
403 	,stu_rec.data_type);
404                       EXCEPTION WHEN OTHERS THEN
405                         hr_legislation.hrrunprc_trace_on;
406                         hr_utility.trace('ins ff_contexts');
407                         hr_utility.trace('context_id  ' ||
408                           to_char(stu_rec.c_surrogate_key));
409                         hr_utility.trace('context_name  ' ||
410                           stu_rec.c_true_key);
411                         hr_utility.trace('context_level  ' ||
412                           to_char(stu_rec.context_level));
413                         hr_utility.trace('datatype  ' ||
414                           stu_rec.data_type);
415                         hr_legislation.hrrunprc_trace_off;
416                         raise;
417                       END;
418 
419 
420 	-- Delete delivered row now it has been installed
421 
422 	remove;
423 
424     END transfer_row;
425 
426 BEGIN
427 
428     -- This is the main loop to perform the installation logic. A cursor
429     -- is opened to control the loop, and each row returned is placed
430     -- into a record defined within the main procedure so each sub
431     -- procedure has full access to all returrned columns. For each
432     -- new row returned, a new savepoint is declared. If at any time
433     -- the row is in error a rollback is performed to the savepoint
434     -- and the next row is returned. Ownership details are checked and
435     -- if the row is required then the surrogate id is updated and the
436     -- main transfer logic is called.
437 
438     IF p_phase = 1 THEN
439         check_next_sequence;
440     END IF;
441 
442     FOR delivered IN stu LOOP
443 
444 	-- Uses main cursor stu to impilicity define a record
445 
446 
447         savepoint new_context_name;
448 
449         -- Make all cursor columns available to all procedures
450 
451         stu_rec := delivered;
452 
453 	IF p_phase = 1 THEN update_uid; END IF;
454 
455         IF valid_ownership THEN
456 
457             -- Test the row onerships for the current row
458 
459 
460 	    transfer_row;
461 
462        END IF;
463 
464     END LOOP;
465 
466 END install_ffc;
467 
468 --****************************************************************************
469 -- INSTALLATION PROCEDURE FOR : FF_FORMULA_TYPES_S
470 --****************************************************************************
471 
472 PROCEDURE install_fft (p_phase IN number)
473 -----------------------------------------
474 IS
475     -- Install startup formula types into a live account. The procedure compares
476     -- delivered types to live types. If different the delivered types will be
477     -- installed.
478 
479     l_null_return varchar2(1); 		-- For 'select null' statements
480     l_new_surrogate_key number(15); 	-- New surrogate key for delivery row
481     l_old_surrogate_key number(15);
482     l_number_of_ftcu number;
483 
484     CURSOR stu				-- Selects all rows from startup entity
485     IS
486 	select formula_type_name c_true_key
487 	,      rowid
488 	,      formula_type_id c_surrogate_key
489 	,      type_description
490 	,      last_update_date
491 	,      last_updated_by
492 	,      last_update_login
493 	,      created_by
494 	,      creation_date
495 	from   hr_s_formula_types;
496 
497     CURSOR ftcu (p_ftype_id number)	-- Cursor for install context usages
498     IS
499 	select *
500 	from   hr_s_ftype_context_usages
501 	where  formula_type_id = p_ftype_id;
502 
503     stu_rec stu%ROWTYPE;		-- Record definition for cursor select
504 
505 
506     PROCEDURE crt_exc (exception_type IN varchar2)
507     ----------------------------------------------
508     IS
509 	-- Reports any exceptions during the delivery of startup data to
510 	-- FF_FORMULA_TYPES_S
511 
512     BEGIN
513 
514 	-- When the installation procedures encounter an error that cannot
515 	-- be handled, an exception is raised and all work is rolled back
516 	-- to the last savepoint. The installation process then continues
517 	-- with the next primary key to install. The same exception will
518 	-- not be raised more than once.
519 
520 
521 	rollback to new_formula_type_name;
522 
523 	hr_legislation.insert_hr_stu_exceptions('ff_formula_types'
524         ,      stu_rec.c_surrogate_key
525         ,      exception_type
526         ,      stu_rec.c_true_key);
527 
528 
529     END crt_exc;
530 
531     PROCEDURE check_next_sequence
532     -----------------------------
533     IS
534         CURSOR c_fft1 IS
535         select distinct null
536         from   ff_formula_types a
537         where  exists
538             (select null
542         --
539              from   hr_s_formula_types b
540              where  a.formula_type_id = b.formula_type_id
541             );
543         v_sequence_number number(9);
544         v_min_delivered number(9);
545         v_max_delivered number(9);
546 
547 	-- Surrogate id conflicts may arise from two scenario's:
548 	-- 1. Where the newly select sequence value conflicts with values
549 	--    in the STU tables.
550 	-- 2. Where selected surrogate keys, from the installed tables,
551 	--    conflict with other rows in the STU tables.
552 	--
553 	-- Both of the above scenario's are tested for.
554 	-- The first is a simple match, where if a value is detected in the
555 	-- STU tables and the installed tables then a conflict is detected. In
556 	-- This instance all STU surrogate keys, for this table, are updated.
557 	-- The second is tested for using the sequences.
558 	-- If the next value from the live sequence is within the range of
559 	-- delivered surrogate id's then the live sequence must be incremented.
560 	-- If no action is taken, then duplicates may be introduced into the
561 	-- delivered tables, and child rows may be totally invalidated.
562 	-- This procedure will check three sequences
563 
564     BEGIN
565 
566 
567 	BEGIN	--check that the installde routes will not conflict
568 		--with the delivered values
569 
570             --
571             open c_fft1;
572             fetch c_fft1 into l_null_return;
573                 IF c_fft1%NOTFOUND OR c_fft1%NOTFOUND IS NULL THEN
574                         RAISE NO_DATA_FOUND;
575                 END IF;
576             close c_fft1;
577             --
578 	    --conflict may exist
579 	    --update all formula_type_id's to remove conflict
580 
581 	    update hr_s_formula_types
582 	    set    formula_type_id = formula_type_id - 50000000;
583 
584 	    update hr_s_formulas_f
585             set    formula_type_id = formula_type_id - 50000000;
586 
587 	    update hr_s_ftype_context_usages
588             set    formula_type_id = formula_type_id - 50000000;
589 
590 	    update hr_s_qp_reports
591             set    formula_type_id = formula_type_id - 50000000;
592 
593 	    update hr_s_application_ownerships
594 	    set    key_value = key_value - 50000000
595 	    where  key_name = 'FORMULA_TYPE_ID';
596 
597 	EXCEPTION WHEN NO_DATA_FOUND THEN NULL;
598 
599 	END; --check of formula_type_id
600 
601 
602 
603         select min(formula_type_id) - (count(*) *3)
604         ,      max(formula_type_id) + (count(*) *3)
605         into   v_min_delivered
606         ,      v_max_delivered
607         from   hr_s_formula_types;
608 
609         select ff_formula_types_s.nextval
610         into   v_sequence_number
611         from   dual;
612 
613         IF v_sequence_number
614           BETWEEN v_min_delivered AND v_max_delivered THEN
615 
616             hr_legislation.munge_sequence('FF_FORMULA_TYPES_S',
617                                           v_sequence_number,
618                                           v_max_delivered);
619 
620         END IF;
621 
622     END check_next_sequence;
623 
624     PROCEDURE update_uid
625     --------------------
626     IS
627 	-- Subprogram to update surrogate UID and all occurrences in child rows
628 
629     BEGIN
630 
631 
632         BEGIN
633 
634             select distinct formula_type_id
635 	    into   l_new_surrogate_key
636 	    from   ff_formula_types
637 	    where  formula_type_name = stu_rec.c_true_key;
638 
639         EXCEPTION WHEN NO_DATA_FOUND THEN
640 
641 	   select ff_formula_types_s.nextval
642 	   into   l_new_surrogate_key
643 	   from   dual;
644 
645            WHEN TOO_MANY_ROWS THEN
646            hr_legislation.hrrunprc_trace_on;
647            hr_utility.trace('multiple ftype ' || stu_rec.c_true_key);
648            hr_legislation.hrrunprc_trace_off;
649            raise;
650        END;
651 
652        -- Update all child entities
653 
654        update hr_s_formula_types
655        set    formula_type_id = l_new_surrogate_key
656        where  formula_type_id = stu_rec.c_surrogate_key;
657 
658        update hr_s_application_ownerships
659        set    key_value = to_char(l_new_surrogate_key)
660        where  key_value = to_char(stu_rec.c_surrogate_key)
661        and    key_name = 'FORMULA_TYPE_ID';
662 
663        update hr_s_formulas_f
664        set    formula_type_id = l_new_surrogate_key
665        where  formula_type_id = stu_rec.c_surrogate_key;
666 
667        update hr_s_ftype_context_usages
668        set    formula_type_id = l_new_surrogate_key
669        where  formula_type_id = stu_rec.c_surrogate_key;
670 
671        update hr_s_qp_reports
672        set    formula_type_id = l_new_surrogate_key
673        where  formula_type_id = stu_rec.c_surrogate_key;
674 
675     END update_uid;
676 
677     PROCEDURE remove
678     ----------------
679     IS
680         -- Remove a row from the startup/delivered tables
681 
682     BEGIN
683 
684         delete from hr_s_formula_types
685         where  rowid = stu_rec.rowid;
686 
690     END remove;
687         delete from hr_s_ftype_context_usages
688         where  formula_type_id = l_new_surrogate_key;
689 
691 
692     FUNCTION valid_ownership RETURN BOOLEAN
693     ---------------------------------------
694     IS
695     --
696     CURSOR c_fft2 IS
697         select null --if exception raised then this row is not needed
698         from   dual
699         where  exists (
700                select null
701                from   hr_s_application_ownerships a
702                ,      fnd_product_installations b
703                ,      fnd_application c
704                where  a.key_name = 'FORMULA_TYPE_ID'
705                and    a.key_value = l_new_surrogate_key
706                and    a.product_name = c.application_short_name
707                and    c.application_id = b.application_id
708                and    ((b.status = 'I' and c.application_short_name <> 'PQP')
709                        or
710                        (b.status in ('I', 'S') and c.application_short_name = 'PQP')));
711     --
712     -- If for a given formula_type_id, there is a difference of any sort between
713     -- what is on the live table to what is being delivered then we must
714     -- invalidate and recreate the usages which will invalidate potentially
715     -- many formulae. This if there is no mismatch between delivered and
716     -- live data then we will remove the formula type from the hr_s tables
717     -- so eleiminating the need for formula invalidation.
718     -- new version. Only need for live to not be a superset of HR_S
719     CURSOR c_fft3 IS
720       select 1
721       from   dual
722       where  exists
723         (select hfcu.context_id
724          from   hr_s_ftype_context_usages hfcu
725          where  hfcu.formula_type_id = l_new_surrogate_key
726          MINUS
727          select fcu.context_id
728          from   ff_ftype_context_usages fcu
729          where  fcu.formula_type_id = l_new_surrogate_key);
730     --
731     BEGIN
732 	-- This routine only operates in phase 1. Rows are present in the
733 	-- table hr_application_ownerships in the delivery account, which
734 	-- dictate which products a piece of data is used for. If the query
735 	-- returns a row, then this data is required, and the function will
736 	-- return true. If no rows are returned and an exception is raised,
737 	-- then this row is not required and may be deleted from the delivery
738 	-- tables.
739 
740 	-- If legislation code and subgroup code are included on the delivery
741 	-- tables, a check must be made to determine if the data is defined for
742 	-- a specific subgroup. If so the subgroup must be 'A'ctive for this
743 	-- installation.
744 
745 	-- A return code of TRUE indicates that the row is required.
746 
747 	-- The exception is raised within this procedure if no rows are returned
748 	-- in this select statement. If no rows are returned then one of the
749 	-- following is true:
750 	--     1. No ownership parameters are defined.
751 	--     2. The products, for which owning parameters are defined, are not
752 	--        installed with as status of 'I'.
753 	--     3. The data is defined for a legislation subgroup that is not active.
754 
755      IF p_phase <> 1 THEN	-- Only perform in phase 1
756        return TRUE;
757      END IF;
758      --
759      BEGIN
760         open c_fft2;
761         fetch c_fft2 into l_null_return;
762            IF c_fft2%NOTFOUND THEN
763            close c_fft2;
764            RAISE NO_DATA_FOUND;
765         END IF;
766         close c_fft2;
767         --
768      EXCEPTION WHEN NO_DATA_FOUND THEN
769 
770 	-- Row not needed for any installed product
771 	remove;
772 	return FALSE;	-- Indicates row not needed
773 
774      END;
775 
776      BEGIN
777 
778       -- Now check to see if we have to reinstall this row by checking
779       -- if the ftype usages all match. If any don't then we must reinstall
780       -- the formula_type and its usages which will mean potentially having
781       -- to recompile many formulae
782       IF p_phase <> 1 THEN
783         return TRUE;
784       END IF;
785 
786       -- check if any diffs between ftcus in delivered and live
787       -- this cursor doesnt cater when there are no ftcus so check for
788       -- this first
789 
790       select count(*)
791       into   l_number_of_ftcu
792       from   hr_s_ftype_context_usages
793       where  formula_type_id = l_new_surrogate_key;
794 
795       if l_number_of_ftcu <> 0 then
796         open c_fft3;
797         fetch c_fft3 into l_null_return;
798         IF c_fft3%NOTFOUND THEN
799            close c_fft3;
800            remove; -- everything between live and delivered matches
801         END IF;
802         close c_fft3;
803       end if;
804       --
805     EXCEPTION WHEN OTHERS THEN
806       null;
807     END;
808 
809     return TRUE;
810 
811     END valid_ownership;
812 
813     PROCEDURE transfer_row
814     ----------------------
815     IS
816 
817     CURSOR c_fft5 (usages_context_id number) IS
818     select null
819     from   ff_contexts
820     where  context_id = usages_context_id;
821     --
822 
826         set    type_description = stu_rec.type_description
823     BEGIN
824 
825         update ff_formula_types
827         ,      last_update_date = stu_rec.last_update_date
828         ,      last_updated_by = stu_rec.last_updated_by
829         ,      last_update_login = stu_rec.last_update_login
830         ,      created_by = stu_rec.created_by
831         ,      creation_date = stu_rec.creation_date
832         where  formula_type_name = stu_rec.c_true_key;
833 
834         IF SQL%NOTFOUND THEN
835 
836             -- This formula type does not exist
837 
838            BEGIN
839 	    insert into ff_formula_types
840 	    (formula_type_name
841 	    ,formula_type_id
842             ,type_description
843 	    ,last_update_date
844 	    ,last_updated_by
845 	    ,last_update_login
846 	    ,created_by
847 	    ,creation_date
848 	    )
849 	    values
850 	    (stu_rec.c_true_key
851 	    ,stu_rec.c_surrogate_key
852 	    ,stu_rec.type_description
853 	    ,stu_rec.last_update_date
854 	    ,stu_rec.last_updated_by
855 	    ,stu_rec.last_update_login
856 	    ,stu_rec.created_by
857 	    ,stu_rec.creation_date
858  	    );
859                       EXCEPTION WHEN OTHERS THEN
860                         hr_legislation.hrrunprc_trace_on;
861                         hr_utility.trace('ins ff_formula_types');
862                         hr_utility.trace('formula_type_id  ' ||
863                           to_char(stu_rec.c_surrogate_key));
864                         hr_utility.trace('formula_type_name  ' ||
865                           stu_rec.c_true_key);
866                         hr_legislation.hrrunprc_trace_off;
867                         raise;
868                       END;
869 
870 
871 	END IF;
872 
873    	-- Now loop for all context usages to install. First a check must be made
874 	-- to see if the context referenced in this row is installed in the live
875 	-- tables. If not then the transfer for this whole formula type must not
876 	-- proceed. The actual insert statement is within a phase value check
877 	-- to allow any errors with parent contexts to be highlighted in pahse 1.
878 	-- the last final delete will only occur in phase 2, since only in phase 2
879 	-- will the row have been transferred.
880 	-- All the live context usages must be deleted first
881 
882         FOR usages IN ftcu(l_new_surrogate_key) LOOP
883 
884 	    BEGIN
885 
886                 delete ff_compiled_info_f f
887                 where  f.formula_id in (
888                   select distinct a.formula_id
889                   from   ff_formulas_f a,
890                          ff_fdi_usages_f b,
891                          ff_contexts c
892                   where  a.formula_type_id = stu_rec.c_surrogate_key
893                   and    a.formula_id = b.formula_id
894                   and    b.item_name = upper(c.context_name)
895                   and    c.context_id = usages.context_id
896                   and    b.usage = 'U');
897 
898                 delete ff_fdi_usages_f f
899                 where  f.formula_id in (
900                   select distinct a.formula_id
901                   from   ff_formulas_f a,
902                          ff_fdi_usages_f b,
903                          ff_contexts c
904                   where  a.formula_type_id = stu_rec.c_surrogate_key
905                   and    a.formula_id = b.formula_id
906                   and    b.item_name = upper(c.context_name)
907                   and    c.context_id = usages.context_id
908                   and    b.usage = 'U');
909 
910                 delete from ff_ftype_context_usages
911                 where  formula_type_id = stu_rec.c_surrogate_key
912                 and context_id=usages.context_id;
913 
914                 open c_fft5 (usages.context_id);
915                 fetch c_fft5 into l_null_return;
916                 IF c_fft5%NOTFOUND OR c_fft5%NOTFOUND IS NULL THEN
917                   RAISE NO_DATA_FOUND;
918                 END IF;
919                 close c_fft5;
920 
921                 insert into ff_ftype_context_usages
922                 (formula_type_id
923                 ,context_id)
924                 values
925                 (usages.formula_type_id
926                 ,usages.context_id);
927 
928             EXCEPTION WHEN NO_DATA_FOUND THEN
929 
930 	        -- Parent context not present
931 
932 
933 	        crt_exc('Context referenced by child usage is not present');
934 
935 	        -- Get next formula type to install
936 
937                 return;
938 
939                      WHEN OTHERS THEN
940                         hr_legislation.hrrunprc_trace_on;
941                         hr_utility.trace('ins ff_ftype_context_usages');
942                         hr_utility.trace('formula_type_id  ' ||
943                           to_char(usages.formula_type_id));
944                         hr_utility.trace('context_id  ' ||
945                           to_char(usages.context_id));
946                         hr_utility.trace('formula_type_name  ' ||
947                           stu_rec.c_true_key);
948                         hr_legislation.hrrunprc_trace_off;
952 	END LOOP usages;
949                         raise;
950 	    END;
951 
953 
954 
955 	-- Delete delivered row now it has been installed
956 
957         remove;
958 
959     END transfer_row;
960 
961 BEGIN
962 
963     -- This is the main loop to perform the installation logic. A cursor
964     -- is opened to control the loop, and each row returned is placed
965     -- into a record defined within the main procedure so each sub
966     -- procedure has full access to all returrned columns. For each
967     -- new row returned, a new savepoint is declared. If at any time
968     -- the row is in error a rollback iss performed to the savepoint
969     -- and the next row is returned. Ownership details are checked and
970     -- if the row is required then the surrogate id is updated and the
971     -- main transfer logic is called.
972 
973     IF p_phase = 1 THEN
974 	check_next_sequence;
975     END IF;
976 
977     FOR delivered IN stu LOOP
978 
979 	-- Uses main cursor stu to impilicity define a record
980 
981 
982         savepoint new_formula_type_name;
983 
984 	-- Make all cursor columns available to all procedures
985 
986         stu_rec := delivered;
987 
988         IF p_phase = 1 THEN
989             update_uid;
990         END IF;
991 
992         IF p_phase = 2 THEN
993 	    l_new_surrogate_key := stu_rec.c_surrogate_key;
994 	END IF;
995 
996         IF valid_ownership THEN
997 
998 	    -- Test the row onerships for the current row
999 
1000 
1001  	    if p_phase = 2 THEN transfer_row; end if;
1002 
1003 	END IF;
1004 
1005     END LOOP;
1006 
1007 END install_fft;
1008 
1009 --****************************************************************************
1010 -- INSTALLATION PROCEDURE FOR : FF_FORMULAS_F
1011 --****************************************************************************
1012 
1013 PROCEDURE install_formulas (p_phase IN NUMBER)
1014 ----------------------------------------------
1015 IS
1016 	-- Install procedure to transfer startup delivered ff_formulass into a
1017 	-- live account, and remove the then delivered rows from the delivery
1018 	-- account.
1019 	-- This procedure is called in two phase. Only in the second phase are
1020 	-- details transferred into live tables. The parameter p_phase holds
1021 	-- the phase number.
1022 
1023 	row_in_error exception;
1024         v_formula_text long;
1025         vlive_formula_text long;
1026 	l_current_proc varchar2(80) := 'hr_legislation.install_formulas';
1027 	l_new_formula_id        number(15);
1028 	l_null_return           varchar2(1);
1029 
1030     CURSOR c_distinct
1031     IS
1032 	-- select statement used for the main loop. Each row return is used
1033 	-- as the commit unit, since each true primary key may have many date
1034 	-- effective rows for it.
1035 	-- The selected primary key is then passed into the second driving
1036 	-- cursor statement as a parameter, and all date effective rows for
1037 	-- this primary key are then selected.
1038 
1039        select max(effective_end_date) c_end
1040        ,      formula_id c_surrogate_key
1041        ,      formula_type_id
1042        ,      formula_name c_true_key
1043        ,      legislation_code
1044        from   hr_s_formulas_f
1045        group  by formula_id
1046        ,         formula_type_id
1047        ,         formula_name
1048        ,         legislation_code;
1049 
1050     CURSOR c_each_row (pc_formula_id varchar2)
1051     IS
1052 	-- Selects all date effective rows for the current true primary key
1053 	-- The primary key has already been selected using the above cursor.
1054 	-- This cursor accepts the primary key as a parameter and selects all
1055 	-- date effective rows for it.
1056 
1057 	select *
1058         from   hr_s_formulas_f
1059         where  formula_id = pc_formula_id;
1060 
1061     -- These records are defined here so all sub procedures may use the
1062     -- values selected. This saves the need for all sub procedures to have
1063     -- a myriad of parameters passed. The cursors are controlled in FOR
1064     -- cursor LOOPs. When a row is returned the whole record is copied into
1065     -- these record definitions.
1066 
1067     r_distinct c_distinct%ROWTYPE;
1068     r_each_row c_each_row%ROWTYPE;
1069     l_dummy varchar2(1);
1070 
1071     PROCEDURE crt_exc (exception_type IN varchar2)
1072     ----------------------------------------------
1073     IS
1074 	-- Reports any exceptions during the delivery of startup data to
1075 	-- FF_FORMULAS_F
1076     BEGIN
1077 	-- When the installation procedures encounter an error that cannot
1078 	-- be handled, an exception is raised and all work is rolled back
1079 	-- to the last savepoint. The installation process then continues
1080 	-- with the next primary key to install. The same exception will
1081 	-- not be raised more than once.
1082 
1083 	rollback to new_formula_name;
1084 
1085 	hr_legislation.insert_hr_stu_exceptions('ff_formulas_f'
1086         ,      r_distinct.c_surrogate_key
1087         ,      exception_type
1088         ,      r_distinct.c_true_key);
1089 
1093     PROCEDURE remove (v_id IN number)
1090 
1091     END crt_exc;
1092 
1094     ---------------------------------
1095     IS
1096 	-- Subprogram to delete a row from the delivery tables, and all child
1097 	-- application ownership rows
1098 
1099     BEGIN
1100 
1101 
1102 	delete from hr_s_formulas_f
1103 	where  formula_id = v_id;
1104 
1105     END remove;
1106 
1107     PROCEDURE check_next_sequence
1108     -----------------------------
1109     IS
1110 
1111 	v_sequence_number number(9);
1112 	v_min_delivered number(9);
1113 	v_max_delivered number(9);
1114 
1115 	-- Surrogate id conflicts may arise from two scenario's:
1116 	-- 1. Where the newly select sequence value conflicts with values
1117 	--    in the STU tables.
1118 	-- 2. Where selected surrogate keys, from the installed tables,
1119 	--    conflict with other rows in the STU tables.
1120 	--
1121 	-- Both of the above scenario's are tested for.
1122 	-- The first is a simple match, where if a value is detected in the
1123 	-- STU tables and the installed tables then a conflict is detected. In
1124 	-- This instance all STU surrogate keys, for this table, are updated.
1125 	-- The second is tested for using the sequences.
1126 	-- If the next value from the live sequence is within the range of
1127 	-- delivered surrogate id's then the live sequence must be incremented.
1128 	-- If no action is taken, then duplicates may be introduced into the
1129 	-- delivered tables, and child rows may be totally invalidated.
1130 
1131     BEGIN
1132 
1133 
1134 	BEGIN	--check that the installed id's will not conflict
1135 		--with the delivered values
1136 
1137 
1138 	    select distinct null
1139 	    into   l_null_return
1140 	    from   ff_formulas_f a
1141 	    where  exists
1142 		(select null
1143 		 from   hr_s_formulas_f b
1144 		 where  a.formula_id = b.formula_id
1145 		);
1146 
1147 	    --conflict may exist
1148 	    --update all formula_id's to remove conflict
1149 
1150 	    update /*+NO_INDEX*/ hr_s_formulas_f
1151 	    set    formula_id = formula_id - 50000000;
1152 
1153 	    update /*+NO_INDEX*/ hr_s_qp_reports
1154             set    formula_id = formula_id - 50000000;
1155 
1156 	    update /*+NO_INDEX*/ hr_s_element_types_f
1157             set    formula_id = formula_id - 50000000;
1158 
1159             update /*+NO_INDEX*/ hr_s_element_types_f
1160             set    iterative_formula_id = iterative_formula_id - 50000000;
1161 
1162             update /*+NO_INDEX*/ hr_s_element_types_f
1163             set    proration_formula_id = proration_formula_id - 50000000;
1164 
1165             update /*+NO_INDEX*/ hr_s_input_values_f
1166             set    formula_id = formula_id - 50000000;
1167 
1168             update /*+NO_INDEX*/ hr_s_status_processing_rules_f
1169             set    formula_id = formula_id - 50000000;
1170 
1171             update /*+NO_INDEX*/ hr_s_user_columns
1172             set    formula_id = formula_id - 50000000;
1173 
1174 	    update hr_s_application_ownerships
1175 	    set    key_value = key_value - 50000000
1176 	    where  key_name = 'FORMULA_ID';
1177 
1178 	    update /*+NO_INDEX*/ hr_s_magnetic_records
1179 	    set    formula_id = formula_id - 50000000;
1180 
1181             update hr_s_legislation_rules
1182             set    rule_mode =
1183 		to_char(fnd_number.canonical_to_number(rule_mode) - 50000000)
1184             where  rule_type = 'LEGISLATION_CHECK_FORMULA';
1185 
1186 	EXCEPTION WHEN NO_DATA_FOUND THEN NULL;
1187 
1188 	END; --check of formula_id
1189 
1190 
1191         select min(formula_id) - (count(*) *3)
1192         ,      max(formula_id) + (count(*) *3)
1193         into   v_min_delivered
1194         ,      v_max_delivered
1195         from   hr_s_formulas_f;
1196 
1197         select ff_formulas_s.nextval
1198         into   v_sequence_number
1199         from   dual;
1200 
1201         IF v_sequence_number
1202 	  BETWEEN v_min_delivered AND v_max_delivered THEN
1203 
1204             hr_legislation.munge_sequence('FF_FORMULAS_S',
1205                                           v_sequence_number,
1206                                           v_max_delivered);
1207         END IF;
1208 
1209     END check_next_sequence;
1210 
1211     PROCEDURE update_uid
1212     --------------------
1213     IS
1214 	-- Subprogram to update surrogate UID and all occurrences in child rows
1215 
1216 	-- See if this primary key is already installed. If so then the sorrogate
1217 	-- key of the delivered row must be updated to the value in the installed
1218 	-- tables. If the row is not already present then select the next value
1219 	-- from the sequence. In either case all rows for this primary key must
1220 	-- be updated, as must all child references to the old surrogate uid.
1221 
1222     BEGIN
1223 
1224 
1225 	BEGIN
1226 
1227 	    select distinct formula_id
1228 	    into   l_new_formula_id
1229 	    from   ff_formulas_f
1230 	    where  formula_name = r_distinct.c_true_key
1231 	    and    formula_type_id = r_distinct.formula_type_id
1232 	    and    business_Group_id is null
1233             and    ((legislation_code is NULL and r_distinct.legislation_code is NULL)
1237 	EXCEPTION WHEN NO_DATA_FOUND THEN
1234                     or (r_distinct.legislation_code=legislation_code));
1235 
1236 
1238 
1239 
1240 	    select ff_formulas_s.nextval
1241 	    into   l_new_formula_id
1242 	    from   dual;
1243 
1244              WHEN TOO_MANY_ROWS THEN
1245 
1246                         hr_legislation.hrrunprc_trace_on;
1247                         hr_utility.trace('sel ff_formulas_f TMR');
1248                         hr_utility.trace('formula_name ' ||
1249                           r_distinct.c_true_key);
1250                         hr_utility.trace('formula_type_id  ' ||
1251                           to_char(r_distinct.formula_type_id));
1252                         hr_utility.trace(':lc: ' || ':' ||
1253                           r_distinct.legislation_code || ':');
1254                         hr_legislation.hrrunprc_trace_off;
1255                         raise;
1256 	END;
1257 
1258 	update hr_s_formulas_f
1259         set    formula_id = l_new_formula_id
1260         where  formula_id = r_distinct.c_surrogate_key;
1261 
1262         update hr_s_application_ownerships
1263         set    key_value = to_char(l_new_formula_id)
1264         where  key_value = to_char(r_distinct.c_surrogate_key)
1265         and    key_name = 'FORMULA_ID';
1266 
1267         update hr_s_qp_reports
1268         set    formula_id = l_new_formula_id
1269         where  formula_id = r_distinct.c_surrogate_key;
1270 
1271         update hr_s_element_Types_f
1272         set    formula_id = l_new_formula_id
1273         where  formula_id = r_distinct.c_surrogate_key;
1274 
1275         update hr_s_element_Types_f
1276         set    iterative_formula_id = l_new_formula_id
1277         where  iterative_formula_id = r_distinct.c_surrogate_key;
1278 
1279         update hr_s_element_Types_f
1280         set    proration_formula_id = l_new_formula_id
1281         where  proration_formula_id = r_distinct.c_surrogate_key;
1282 
1283         update hr_s_input_values_f
1284         set    formula_id = l_new_formula_id
1285         where  formula_id = r_distinct.c_surrogate_key;
1286 
1287         update hr_s_status_processing_rules_f
1288         set    formula_id = l_new_formula_id
1289         where  formula_id = r_distinct.c_surrogate_key;
1290 
1291         update hr_s_user_columns
1292         set    formula_id = l_new_formula_id
1293         where  formula_id = r_distinct.c_surrogate_key;
1294 
1295 	update hr_s_magnetic_records
1296         set    formula_id = l_new_formula_id
1297         where  formula_id = r_distinct.c_surrogate_key;
1298 
1299 	update hr_s_legislation_rules
1300 	set    rule_mode = to_char(l_new_formula_id)
1301         where  rule_mode = to_char(r_distinct.c_surrogate_key)
1302 	and    rule_type = 'LEGISLATION_CHECK_FORMULA';
1303 
1304 
1305     END update_uid;
1306 
1307     PROCEDURE validity_checks
1308     -------------------------
1309     IS
1310 	-- After all rows for a primary key have been delivered, entity specific
1311 	-- checks must be performed to check to validity of the data that has
1312 	-- just been installed.
1313 
1314     BEGIN
1315 
1316 
1317         IF p_phase =2 THEN
1318 	    l_new_formula_id := r_distinct.c_surrogate_key;
1319 	END IF;
1320 
1321 	-- Start child check 1
1322 
1323         BEGIN
1324 
1325 	    -- Check input values first
1326 
1327 	    select distinct null
1328 	    into   l_null_return
1329 	    from   pay_input_values_f
1330 	    where  effective_end_date > r_distinct.c_end
1331 	    and    formula_id = l_new_formula_id
1332 	    and    business_group_id is not null;
1333 
1334 
1335 	    crt_exc('User created input value exists after the new end date');
1336 
1337             return;
1338 
1339 	EXCEPTION WHEN NO_DATA_FOUND THEN
1340 
1341 	    null;
1342 
1343 	END;
1344 
1345         BEGIN
1346 
1347 	    -- Check status processing rules now
1348 
1349 	    select distinct null
1350 	    into   l_null_return
1351 	    from   pay_status_processing_rules_f
1352             where  effective_end_date > r_distinct.c_end
1353             and    formula_id = l_new_formula_id
1354             and    business_group_id is not null;
1355 
1356 
1357             crt_exc('User created process rule exists after the new end date');
1358 
1359 	    return;
1360 
1361         EXCEPTION WHEN NO_DATA_FOUND THEN
1362 
1363 	    null;
1364 
1365         END;
1366 
1367     END validity_checks;
1368 
1369     FUNCTION check_parents RETURN BOOLEAN
1370     -------------------------------------
1371     IS
1372 	-- Check the integrity of the references to parent data, before allowing
1373 	-- data to be installed. No parents can exist in the startup tables, since
1374 	-- this will violate constraints when the row is installed, also the
1375 	-- parent uid's must exist in the installed tables already.
1376 
1377 	-- This function will RETURN TRUE if a parent row still exists in the
1378 	-- delivery account. All statements drop through to a RETURN FALSE.
1379 
1380 	-- This procedure is only called in phase 2. The logic to check if
1381 	-- a given parental foriegn key exists is split into two parts for
1385 	-- failed, and this installation must not go ahead. If no data is
1382 	-- every foriegn key. The first select from the delivery tables.
1383 
1384 	-- If a row is founnd then the installation of the parent must have
1386 	-- found, ie: an exception is raised, the installation is valid.
1387 
1388 	-- The second check looks for a row in the live tables. If no rows
1389 	-- are returned then this installation is invalid, since this means
1390 	-- that the parent referenced by this row is not present in the
1391 	-- live tables.
1392 
1393 	-- Return code of true indicates that all parental data is correct.
1394 
1395     BEGIN
1396 
1397 
1398 	-- Start first parent check
1399 
1400 	BEGIN
1401 
1402 	    -- Check first parent does not exist in the delivery tables
1403 
1404 	    select distinct null
1405 	    into   l_NULL_RETURN
1406 	    from   hr_s_formula_types
1407 	    where  formula_type_id = r_each_row.formula_type_id;
1408 
1409 
1410 	    crt_exc('Parent formula type still exists in delivery tables');
1411 
1412 	    -- Parent still exists, ignore this row
1413 
1414 	    return FALSE;
1415 
1416 	EXCEPTION WHEN NO_DATA_FOUND THEN
1417 
1418 	    null;
1419 
1420         END;
1421 
1422 	BEGIN
1423 
1424 	    -- Check that the parent exists in the live tables
1425 
1426 
1427 	    select null
1428 	    into   l_null_return
1429 	    from   ff_formula_types
1430 	    where  formula_type_id = r_each_row.formula_type_id;
1431 
1432         EXCEPTION WHEN NO_DATA_FOUND THEN
1433 
1434 
1435 	    crt_exc('Parent formula type does not exist in live tables');
1436 
1437 	    return FALSE;
1438 
1439         END;
1440 
1441 	-- Logic drops through to this statement
1442 
1443 	return TRUE;
1444 
1445     END check_parents;
1446 
1447     FUNCTION valid_ownership RETURN BOOLEAN
1448     ---------------------------------------
1449     IS
1450 	-- Test ownership of this current row
1451 
1452     BEGIN
1453 
1454 	-- This function is split into three distinct parts. The first
1455 	-- checks to see if a row exists with the same primary key, for a
1456 	-- business group that would have access to the delivered row. The
1457 	-- second checks details for data created in other legislations,
1458 	-- in case data is either created with a null legislation or the
1459 	-- delivered row has a null legislation. The last check examines
1460 	-- if this data is actually required for a given install by examining
1461 	-- the product installation table, and the ownership details for
1462 	-- this row.
1463 
1464 	-- A return code of TRUE indicates that the row is required.
1465 
1466 
1467         BEGIN
1468 	    -- Perform a check to see if the primary key has been creeated within
1469 	    -- a visible business group. Ie: the business group is for the same
1470 	    -- legislation as the delivered row, or the delivered row has a null
1471 	    -- legislation. If no rows are returned then the primary key has not
1472 	    -- already been created by a user.
1473 
1474 	    -- The formula must be created for the same formula type.
1475 
1476 
1477             select distinct null
1478             into   l_null_return
1479             from ff_formulas_f a
1480             where a.formula_name = r_distinct.c_true_key
1481             and   a.formula_type_id = r_distinct.formula_type_id
1482             and   a.business_group_id is not null
1483             and   exists (select null from per_business_groups b
1484               where b.business_group_id = a.business_group_id
1485               and b.legislation_code = nvl(r_distinct.legislation_code,b.legislation_code));
1486 
1487 
1488             crt_exc('Row already created in a business group');
1489 
1490 	    -- Indicates this row is not to be transferred
1491 
1492 	    return FALSE;
1493 
1494 	EXCEPTION WHEN NO_DATA_FOUND THEN
1495 
1496 	    null;
1497 
1498         END;
1499 
1500 	-- Now perform a check to see if this primary key has been installed
1501 	-- with a legislation code that would make it visible at the same time
1502 	-- as this row. Ie: if any legislation code is null within the set of
1503 	-- returned rows, then the transfer may not go ahead. If no rows are
1504 	-- returned then the delivered row is fine.
1505 
1506 	-- The formula must be created within the same formula type.
1507 
1508         BEGIN
1509 
1510 
1511 	    select distinct null
1512 	    into   l_null_return
1513 	    from   ff_formulas_f
1514 	    where  formula_name = r_distinct.c_true_key
1515 	    and    formula_type_id = r_distinct.formula_type_id
1516 	    and    legislation_code <> r_distinct.legislation_code
1517 	    and    (legislation_code is null or
1518 		   r_distinct.legislation_code is null );
1519 
1520 
1521             crt_exc('Row already created for a visible legislation');
1522 
1523 	    --indicates this row is not to be transferred
1524 
1525 	    return FALSE;
1526 
1527 	EXCEPTION WHEN NO_DATA_FOUND THEN
1528 
1529 	    null;
1530 
1531 	END;
1532 
1533 	-- The last check examines the product installation table, and the
1537 	-- made to see if that subgroup is active or not. This check only
1534 	-- ownership details for the delivered row. By examining these
1535 	-- tables the row is either deleted or not. If the delivered row
1536 	-- is 'stamped' with a legislation subgroup, then a check must be
1538 	-- needs to be performed in phase 1, since once this decision is
1539 	-- made, it is pontless to perform this logic again.
1540 
1541 	-- The exception is raised within this procedure if no rows are returned
1542 	-- in this select statement. If no rows are returned then one of the
1543 	-- following is true:
1544 	--     1. No ownership parameters are defined.
1545 	--     2. The products, for which owning parameters are defined, are not
1546 	--        installed with as status of 'I'.
1547 	--     3. The data is defined for a legislation subgroup that is not active.
1548 
1549 	IF p_phase <> 1 THEN
1550 	    return TRUE;
1551 	END IF;
1552 
1553 
1554         select null --if exception raised then this row is not needed
1555         into   l_null_return
1556         from   dual
1557         where exists (select null
1558          from   hr_s_application_ownerships a
1559         ,      fnd_product_installations b
1560         ,      fnd_application c
1561         where  a.key_name = 'FORMULA_ID'
1562         and    a.key_value = r_distinct.c_surrogate_key
1563         and    a.product_name = c.application_short_name
1564         and    c.application_id = b.application_id
1565         and    ((b.status = 'I' and c.application_short_name <> 'PQP')
1566                 or
1567                 (b.status in ('I', 'S') and c.application_short_name = 'PQP')));
1568 
1569 
1570 	-- Indicates row is required
1571 
1572 	return TRUE;
1573 
1574     EXCEPTION WHEN NO_DATA_FOUND THEN
1575 
1576 	-- Row not needed for any installed product
1577 
1578 
1579 	remove(r_distinct.c_surrogate_key);
1580 
1581 	-- Indicate row not needed
1582 
1583 	return FALSE;
1584 
1585     END valid_ownership;
1586 
1587 function formula_changed(form_id in number) return boolean is
1588 cursor all_rows(f_id in number) is
1589   select effective_start_date
1590   from   hr_s_formulas_f
1591   where  formula_id = f_id;
1592 begin
1593                     -- First check on  existence
1594 
1595                     BEGIN
1596                       select null
1597                       into  l_dummy
1598                       from  ff_formulas_f
1599                       where formula_id = form_id;
1600                     EXCEPTION when others then
1601                       return TRUE;
1602                     END;
1603 
1604                     -- Check long column for all
1605                     for r_all_rows in all_rows(form_id)
1606                     loop
1607                      BEGIN
1608                       select formula_text
1609                       into   v_formula_text
1610                       from   hr_s_formulas_f
1611                       where  formula_id = form_id
1612                       and    effective_start_date = r_all_rows.effective_start_date;
1613 
1614                       select formula_text
1615                       into   vlive_formula_text
1616                       from   ff_formulas_f
1617                       where  formula_id = form_id
1618                       and    effective_start_date = r_all_rows.effective_start_date;
1619 
1620                       -- First check if non stub formula diff from live
1621                       if (v_formula_text is not null and
1622                           vlive_formula_text is not null and
1623                           v_formula_text <> vlive_formula_text) then
1624                         return TRUE;
1625                       end if;
1626 
1627                      EXCEPTION when others then
1628                       -- not all DT rows in hr_s match to live
1629                       -- or if live version does not exist we need to transfer
1630                         return TRUE;
1631                      END;
1632 
1633                     end loop;
1634 
1635                     -- Now check the rest of the row's columns
1636                     -- not imported by a later hdt
1637                     begin
1638                       select null
1639                       into l_dummy
1640                       from dual
1641                       where not exists
1642                         ((
1643                          select effective_start_date,
1644                                 effective_end_date,
1645                                 description
1646                          from   hr_s_formulas_f
1647                          where  formula_id = form_id
1648                          and    formula_type_id = r_distinct.formula_type_id
1649                          MINUS
1650                          select effective_start_date,
1651                                 effective_end_date,
1652                                 description
1653                          from   ff_formulas_f
1654                          where  formula_id = form_id
1655                          and    formula_type_id = r_distinct.formula_type_id
1656                         )
1657                          UNION
1658                         (
1659                          select effective_start_date,
1663                          where  formula_id = form_id
1660                                 effective_end_date,
1661                                 description
1662                          from   ff_formulas_f
1664                          and    formula_type_id = r_distinct.formula_type_id
1665                          MINUS
1666                          select effective_start_date,
1667                                 effective_end_date,
1668                                 description
1669                          from   hr_s_formulas_f
1670                          where  formula_id = form_id
1671                          and    formula_type_id = r_distinct.formula_type_id
1672                         ));
1673                     -- if we get a row and not the exception then identical
1674                     return FALSE;
1675                     exception
1676                       -- otherwise there is a diff
1677                       when no_data_found then
1678                         return TRUE;
1679                     end;
1680 end formula_changed;
1681 
1682 BEGIN
1683 
1684     -- Two loops are used here. The main loop which select distinct primary
1685     -- key rows and an inner loop which selects all date effective rows for the
1686     -- primary key. The inner loop is only required in phase 2, since only
1687     -- in phase 2 are rows actually transferred. The logic reads as follows:
1688 
1689     --    - Only deal with rows which have correct ownership details and will
1690     --      not cause integrity problems (valid_ownership).
1691 
1692     --    - In Phase 1:
1693     --               - Delete delivery rows where the installed rows are identicle.
1694     --               - The UNION satement compares delivery rows to installed rows.
1695     --                 If the sub query returns any rows, then the delivered
1696     --                 tables and the installed tables are different.
1697 
1698     --     In Phase 2:
1699     --               - Delete from the installed tables using the surrogate id.
1700     --               - If an installed row is to be replaced, the values of
1701     --                 the surrogate keys will be identicle at this stage.
1702     --               - Data will then be deleted from the delivery tables.
1703     --               - Call the installation procedure for any child tables, that
1704     --                 must be installed within the same commit unit. If any
1705     --                 errors occur then rollback to the last declared savepoint.
1706     --               - Check that all integrity rules are still obeyed at the end
1707     --                 of the installation (validity_checks).
1708 
1709     -- An exception is used with this procedure 'row_in_error' in case an error
1710     -- is encountered from calling any function. If this is raised, then an
1711     -- exception is entered into the control tables (crt_exc();) and a rollback
1712     -- is performed.
1713 
1714     IF p_phase = 1 THEN
1715 	check_next_sequence;
1716     END IF;
1717 
1718     FOR formula_names IN c_distinct LOOP
1719 
1720 
1721 	savepoint new_formula_name;
1722 
1723 	r_distinct := formula_names;
1724 
1725 	BEGIN
1726 
1727 
1728 	    IF valid_ownership THEN
1729 
1730 	        -- This row is wanted
1731 
1732 
1733 		IF p_phase = 1 THEN
1734 
1735 
1736 		    -- Get new surrogate id and update child references
1737 
1738 		    update_uid;
1739 
1740 	        ELSE
1741 
1742 		    -- Phase = 2
1743 
1744                     -- Now Ids are matched Check if formula definition is
1745                     -- actually required
1746                     if not  formula_changed(r_distinct.c_surrogate_key) then
1747                       remove(r_distinct.c_surrogate_key);
1748                     else
1749 
1750 		    delete from ff_fdi_usages_f
1751 		    where  formula_id = r_distinct.c_surrogate_key;
1752 
1753 		    delete from ff_compiled_info_f
1754                     where  formula_id = r_distinct.c_surrogate_key;
1755 
1756 		    delete from ff_formulas_f
1757 		    where  formula_id = r_distinct.c_surrogate_key;
1758 
1759 		    FOR each_row IN c_each_row(r_distinct.c_surrogate_key) LOOP
1760 
1761 
1762 		        r_each_row := each_row;
1763 
1764 		        IF NOT check_parents THEN
1765 		            RAISE row_in_error;
1766 		        END IF;
1767 
1768                         BEGIN
1769 		        insert into ff_formulas_f
1770 		        (formula_id
1771 	                ,effective_start_date
1772 	                ,effective_end_date
1773 	                ,business_group_id
1774 	                ,legislation_code
1775 	                ,formula_type_id
1776 	                ,formula_name
1777 	                ,description
1778 	                ,formula_text
1779 	                ,sticky_flag
1780                         ,compile_flag
1781 	                ,last_update_date
1782 		        ,last_updated_by
1783 	                ,last_update_login
1784 	                ,created_by
1785 	                ,creation_date
1786 		        )
1787 		        values
1788 		        (r_each_row.formula_id
1789                         ,r_each_row.effective_start_date
1790                         ,r_each_row.effective_end_date
1794                         ,r_each_row.formula_name
1791                         ,r_each_row.business_group_id
1792                         ,r_each_row.legislation_code
1793                         ,r_each_row.formula_type_id
1795                         ,r_each_row.description
1796                         ,r_each_row.formula_text
1797                         ,r_each_row.sticky_flag
1798                         ,r_each_row.compile_flag
1799                         ,r_each_row.last_update_date
1800                         ,r_each_row.last_updated_by
1801                         ,r_each_row.last_update_login
1802                         ,r_each_row.created_by
1803                         ,r_each_row.creation_date
1804                         );
1805                       EXCEPTION WHEN OTHERS THEN
1806                         hr_legislation.hrrunprc_trace_on;
1807                         hr_utility.trace('ins ff_formulas_f');
1808                         hr_utility.trace('formula_name  ' ||
1809                           r_each_row.formula_name);
1810                         hr_utility.trace('formula_id  ' ||
1811                           to_char(r_each_row.formula_id));
1812                         hr_utility.trace('formula_type_id  ' ||
1813                           to_char(r_each_row.formula_type_id));
1814                         hr_utility.trace(':lc: ' || ':' ||
1815                           r_each_row.legislation_code || ':');
1816                         hr_legislation.hrrunprc_trace_off;
1817                         raise;
1818                       END;
1819 
1820 		        remove(r_distinct.c_surrogate_key);
1821 
1822 		    END LOOP each_row;
1823 
1824 	            validity_checks;
1825 
1826 		    -- This will cause a rollback if error occurs
1827 
1828 	       END IF;
1829 
1830               end if; -- need the row
1831 
1832 
1833 	    END IF;
1834 
1835         EXCEPTION WHEN row_in_error THEN
1836 
1837 	    -- Already rolled back
1838 
1839 	    null;
1840 
1841         END;
1842 
1843     END LOOP formula_names;
1844 
1845 END install_formulas;
1846 
1847 --****************************************************************************
1848 -- INSTALLATION PROCEDURE FOR : FF_ROUTES
1849 --****************************************************************************
1850 
1851 PROCEDURE install_routes (p_phase IN number)
1852 ------------------------
1853 IS
1854     -- Procedure install routes/usages/entities/parameters/parameter values.
1855     -- The main driving installation cursor runs from hr_s_routes. All child
1856     -- rows are installed as cursors driven by the current route_id. The user
1857     -- entities then have child rows installed in a similar way.
1858     -- If the route has not changed, ie:does not need to be installed, it may
1859     -- still remain in the startup tables if there are child user entities to
1860     -- install. When a route is installed, the child rows of parameters and
1861     -- context usages are fully refreshed. Child user entities are stil treated
1862     -- as only being installed if required. Database ietms and parameter values
1863     -- are fully refreshed if the parent user entity is required to be installed.
1864 
1865     l_null_return varchar2(1); 		-- For 'select null' statements
1866     l_new_surrogate_key number(15); 	-- New surrogate key for the delivery row
1867     string varchar2(80);
1868     l_route_id number;
1869     l_route_name varchar2(2000);
1870     l_new_route BOOLEAN;
1871 
1872     CURSOR c_all_159260
1873     IS
1874     select route_id route_id,
1875            route_name route_name
1876     from   hr_s_routes
1877     where  last_update_login = 159260;
1878 
1879     CURSOR stu				-- Selects all rows from startup entity
1880     IS
1881     select route_id c_surrogate_key
1882     ,route_name c_true_key
1883     ,user_defined_flag
1884     ,description
1885     ,text
1886     ,nvl(last_update_date,to_date('01-01-0001','DD-MM-YYYY')) last_update_date
1887     ,last_updated_by
1888     ,last_update_login
1889     ,created_by
1890     ,creation_date
1891     ,optimizer_hint
1892     ,rowid
1893     from   hr_s_routes;
1894 
1895     CURSOR user_entity (r_id IN number)	-- To install all user entities
1896     IS					-- for a given route
1897 	select *
1898    	from   hr_s_user_entities
1899    	where  route_id = r_id;
1900 
1901     CURSOR usage (r_id IN number)	-- To install context usages
1902     IS					-- for a given route
1903 	select distinct *
1904 	from   hr_s_route_context_usages
1905    	where  route_id = r_id;
1906 
1907     CURSOR parameter (r_id IN number)	-- To install all route parameters
1908     IS					-- for a given route
1909 	select ROUTE_PARAMETER_ID
1910 	,      ROUTE_ID
1911 	,      DATA_TYPE
1912 	,      PARAMETER_NAME
1913 	,      SEQUENCE_NO
1914 	,      rowid
1915    	from   hr_s_route_parameters
1916    	where  route_id = r_id;
1917 
1918     CURSOR parameter_value (ue_id IN number)
1919     IS
1920 	-- To install parameter values for a given user entity
1921 
1922 	select *
1923    	from   hr_s_route_parameter_values
1924    	where  user_entity_id = ue_id;
1925 
1926     CURSOR db_item (ue_id IN number)
1927     IS
1928         -- Cursor to install database items for a given user entity
1929 
1930 	select *
1934     stu_rec stu%ROWTYPE;
1931    	from   hr_s_database_items
1932    	where  user_entity_id = ue_id;
1933 
1935 
1936     PROCEDURE crt_exc (exception_type IN varchar2)
1937     ----------------------------------------------
1938     IS
1939 	-- Reports any exceptions during the delivery of startup data to
1940 	-- FF_ROUTES
1941 
1942     BEGIN
1943 	-- When the installation procedures encounter an error that cannot
1944 	-- be handled, an exception is raised and all work is rolled back
1945 	-- to the last savepoint. The installation process then continues
1946 	-- with the next primary key to install. The same exception will
1947 	-- not be raised more than once.
1948 
1949 
1950 	rollback to new_route_name;
1951 
1952 	hr_legislation.insert_hr_stu_exceptions('ff_routes'
1953         ,      stu_rec.c_surrogate_key
1954         ,      exception_type
1955         ,      stu_rec.c_true_key);
1956 
1957 
1958     END crt_exc;
1959 
1960     PROCEDURE check_id_conflicts
1961     ----------------------------
1962     IS
1963 	-- Surrogate id conflicts may arise from two scenario's:
1964 	-- 1. Where the newly select sequence value conflicts with values
1965 	--    in the STU tables.
1966 	-- 2. Where selected surrogate keys, from the installed tables,
1967 	--    conflict with other rows in the STU tables.
1968 	--
1969 	-- Both of the above scenario's are tested for.
1970 	-- The first is a simple match, where if a value is detected in the
1971 	-- STU tables and the installed tables then a conflict is detected. In
1972 	-- This instance all STU surrogate keys, for this table, are updated.
1973 	-- Three tables are tested:
1974 	--   1. ff_routes
1975 	--   2. ff_user_entities
1976 	--   3. ff_route_parameters
1977 	-- The second is tested for using the sequences.
1978 	-- If the next value from the live sequence is within the range of
1979 	-- delivered surrogate id's then the live sequence must be incremented.
1980 	-- If no action is taken, then duplicates may be introduced into the
1981 	-- delivered tables, and child rows may be totally invalidated.
1982 	-- This procedure will check three sequences
1983 	--   1. ff_routes_S
1984 	--   2. ff_user_entities_s
1985 	--   3. ff_route_parameters_s
1986 
1987        v_sequence_number number(9);
1988        v_min_delivered number(9);
1989        v_max_delivered number(9);
1990        --
1991        cursor get_ff_routes is
1992             select distinct null
1993             from   ff_routes a
1994             where  exists
1995                 (select null
1996                  from   hr_s_routes b
1997                  where  a.route_id = b.route_id
1998                 );
1999 
2000         cursor get_ff_route_parameters is
2001             select distinct null
2002             from   ff_route_parameters a
2003             where  exists
2004                 (select null
2005                  from   hr_s_route_parameters b
2006                  where  b.route_parameter_id = a.route_parameter_id
2007                 );
2008 
2009         cursor get_ff_user_entities is
2010             select distinct null
2011             from   ff_user_entities a
2012             where  exists
2013                 (select null
2014                  from   hr_s_user_entities b
2015                  where  a.user_entity_id = b.user_entity_id
2016                 );
2017     --
2018     BEGIN
2019 
2020 	-- Start with check against ff_routes
2021 
2022 
2023 	BEGIN	--check that the installde routes will not conflict
2024 		--with the delivered values
2025 
2026             --
2027             open get_ff_routes;
2028             fetch get_ff_routes into l_null_return;
2029             IF get_ff_routes%NOTFOUND OR get_ff_routes%NOTFOUND IS NULL THEN
2030                  RAISE NO_DATA_FOUND;
2031             END IF;
2032             close get_ff_routes;
2033             --
2034 	    --conflict may exist
2035 	    --update all route_id's to remove conflict
2036 
2037 	    update /*+NO_INDEX*/ hr_s_routes
2038 	    set    route_id = route_id - 50000000;
2039 
2040 	    update hr_s_application_ownerships
2041 	    set    key_value = key_value - 50000000
2042 	    where  key_name = 'ROUTE_ID';
2043 
2044 	    update /*+NO_INDEX*/ hr_s_balance_dimensions
2045 	    set    route_id = route_id - 50000000;
2046 
2047             update /*+NO_INDEX*/ hr_s_dimension_routes
2048             set    route_id = route_id - 50000000;
2049 
2050 	    update /*+NO_INDEX*/ hr_s_route_context_usages
2051 	    set    route_id = route_id - 50000000;
2052 
2053 	    update /*+NO_INDEX*/ hr_s_user_entities
2054             set    route_id = route_id - 50000000;
2055 
2056 	    update /*+NO_INDEX*/ hr_s_route_parameters
2057             set    route_id = route_id - 50000000;
2058 
2059 	EXCEPTION WHEN NO_DATA_FOUND THEN NULL;
2060 
2061 	END; --check of route_id
2062 
2063 
2064 	BEGIN	--check that no conflict exists within the route
2065 		--parameter id's
2066 
2067             --
2068             open get_ff_route_parameters;
2069             fetch get_ff_route_parameters into l_null_return;
2070             IF get_ff_route_parameters%NOTFOUND
2074             close get_ff_route_parameters;
2071             OR get_ff_route_parameters%NOTFOUND IS NULL THEN
2072                 RAISE NO_DATA_FOUND;
2073             END IF;
2075             --
2076 	    --Conflict exists, so update the stu values of the parameter id
2077 
2078 	    update hr_s_route_parameters
2079 	    set    route_parameter_id = route_parameter_id -50000000;
2080 
2081 	    update hr_s_route_parameter_values
2082             set    route_parameter_id = route_parameter_id -50000000;
2083 
2084 	EXCEPTION WHEN NO_DATA_FOUND THEN NULL;
2085 
2086         END; --check of route_parameter_id
2087 
2088 
2089 
2090 	BEGIN	--check that no conflict exists with the id's of the installed
2091 		--user entities, compared with the values of delivered UE's
2092 
2093             --
2094             open get_ff_user_entities;
2095             fetch get_ff_user_entities into l_null_return;
2096             IF get_ff_user_entities%NOTFOUND OR get_ff_user_entities%NOTFOUND IS NULL THEN
2097                  RAISE NO_DATA_FOUND;
2098             END IF;
2099             close get_ff_user_entities;
2100             --
2101 	    --conflict exists, so update the stu values of user_entity_id
2102 
2103 	    update /*+NO_INDEX*/ hr_s_user_entities
2104 	    set    user_entity_id = user_entity_id -50000000;
2105 
2106             update /*+NO_INDEX*/ hr_s_database_items
2107             set    user_entity_id = user_entity_id -50000000;
2108 
2109             update /*+NO_INDEX*/ hr_s_route_parameter_values
2110             set    user_entity_id = user_entity_id -50000000;
2111 
2112             update /*+NO_INDEX*/ hr_s_report_format_items_f
2113             set    user_entity_id = user_entity_id -50000000;
2114 
2115         EXCEPTION WHEN NO_DATA_FOUND THEN NULL;
2116 
2117         END; --check of user_entity_id
2118 
2119 
2120    	select min(route_id) - (count(*) *3)
2121    	,      max(route_id) + (count(*) *3)
2122    	into   v_min_delivered
2123    	,      v_max_delivered
2124    	from   hr_s_routes;
2125 
2126    	select ff_routes_s.nextval
2127    	into   v_sequence_number
2128    	from   dual;
2129 
2130 	IF v_sequence_number
2131 	  BETWEEN v_min_delivered AND v_max_delivered THEN
2132 
2133             hr_legislation.munge_sequence('FF_ROUTES_S',
2134                                           v_sequence_number,
2135                                           v_max_delivered);
2136 
2137         END IF;
2138 
2139 	-- Now check ff_user_entities
2140 
2141 
2142    	select min(user_entity_id) - (count(*) *3)
2143    	,      max(user_entity_id) + (count(*) *3)
2144    	into   v_min_delivered
2145    	,      v_max_delivered
2146    	from   hr_s_user_entities;
2147 
2148    	select ff_user_entities_s.nextval
2149    	into   v_sequence_number
2150    	from   dual;
2151 
2152 	IF v_sequence_number
2153 	  BETWEEN v_min_delivered AND v_max_delivered THEN
2154 
2155             hr_legislation.munge_sequence('FF_USER_ENTITIES_S',
2156                                           v_sequence_number,
2157                                           v_max_delivered);
2158 
2159         END IF;
2160 
2161 	-- Now check ff_route_parameters
2162 
2163 
2164    	select min(route_parameter_id) - (count(*) *3)
2165    	,      max(route_parameter_id) + (count(*) *3)
2166    	into   v_min_delivered
2167    	,      v_max_delivered
2168    	from   hr_s_route_parameters;
2169 
2170    	select ff_route_parameters_s.nextval
2171    	into   v_sequence_number
2172    	from   dual;
2173 
2174 	IF v_sequence_number
2175 	  BETWEEN v_min_delivered AND v_max_delivered THEN
2176 
2177             hr_legislation.munge_sequence('FF_ROUTE_PARAMETERS_S',
2178                                           v_sequence_number,
2179                                           v_max_delivered);
2180 
2181         END IF;
2182 
2183     END check_id_conflicts;
2184 
2185     PROCEDURE update_uid
2186     --------------------
2187     IS
2188         -- Subprogram to update surrogate UID and all occurrences in child rows
2189 
2190 	l_new_parameter_id number(9);
2191 	l_new_entity_id    number(9);
2192 
2193     cursor c_form3(p_route_id number) is
2194       select distinct ffu.formula_id fid
2195       from   ff_fdi_usages_f ffu
2196       where  ffu.item_name in (select fdbi.user_name
2197                                from   ff_database_items fdbi,
2198                                       ff_user_entities fue
2199                                where  fdbi.user_entity_id = fue.user_entity_id
2200                                and    fue.route_id = p_route_id);
2201 
2202     BEGIN
2203 
2204         l_new_surrogate_key := null;
2205 
2206         BEGIN
2207 
2208 	    select distinct route_id
2209 	    into   l_new_surrogate_key
2210 	    from   ff_routes
2211 	    where  route_name = stu_rec.c_true_key
2212             and    user_defined_flag = 'N';
2213 
2214         EXCEPTION WHEN NO_DATA_FOUND THEN
2215 
2216 
2217            select ff_routes_s.nextval
2218            into   l_new_surrogate_key
2219 	   from   dual;
2220 
2221            WHEN TOO_MANY_ROWS THEN
2222                         hr_legislation.hrrunprc_trace_on;
2226                         hr_legislation.hrrunprc_trace_off;
2223                         hr_utility.trace('sel route ff_routes TMR');
2224                         hr_utility.trace('route_name  ' ||
2225                           stu_rec.c_true_key);
2227                         raise;
2228         END;
2229 
2230 
2231 	-- Update all child entities
2232 
2233 
2234         update hr_s_routes
2235         set    route_id = l_new_surrogate_key
2236         where  rowid = stu_rec.rowid;
2237 
2238         update hr_s_application_ownerships
2239         set    key_value = to_char(l_new_surrogate_key)
2240         where  key_value = to_char(stu_rec.c_surrogate_key)
2241         and    key_name = 'ROUTE_ID';
2242 
2243         update hr_s_balance_dimensions
2244         set    route_id = l_new_surrogate_key
2245         where  route_id = stu_rec.c_Surrogate_key;
2246 
2247         update hr_s_dimension_routes
2248         set    route_id = l_new_surrogate_key
2249         where  route_id = stu_rec.c_Surrogate_key;
2250 
2251         update hr_s_route_context_usages
2252         set    route_id = l_new_surrogate_key
2253         where  route_id = stu_rec.c_Surrogate_key;
2254 
2255 
2256         FOR delivered_params IN parameter(stu_Rec.c_Surrogate_key) LOOP
2257 
2258 	    BEGIN --select of new surrogate id
2259 
2260 
2261 	        select route_parameter_id
2262 	        into   l_new_parameter_id
2263 	        from   ff_route_parameters
2264                 where  sequence_no = delivered_params.sequence_no
2265 	        and    parameter_name = delivered_params.parameter_name
2266 	        and    route_id = l_new_surrogate_key;
2267 
2268 	    EXCEPTION WHEN NO_DATA_FOUND THEN
2269 
2270                 /* As this could be a change to either the sequence ordering
2271                    or the parameter naming (or both) be safe and just delete
2272                    all parameters for this route and reimport them from scratch
2273                    so as to avoid any constraint violations */
2274 
2275                /* bug 5501644 */
2276                 for r_form3 in c_form3(l_new_surrogate_key) loop
2277                   delete ff_fdi_usages_f where formula_id = r_form3.fid;
2278                   delete ff_compiled_info_f where formula_id = r_form3.fid;
2279                 end loop;
2280 
2281                 delete ff_route_parameter_values
2282                 where route_parameter_id in (
2283                   select route_parameter_id
2284                   from   ff_route_parameters
2285                   where  route_id = l_new_surrogate_key);
2286 
2287                 delete ff_route_parameters
2288                 where  route_id = l_new_surrogate_key;
2289 
2290 	        select ff_route_parameters_s.nextval
2291 	        into   l_new_parameter_id
2292                 from   dual;
2293 
2294                  WHEN TOO_MANY_ROWS THEN
2295 
2296                         hr_legislation.hrrunprc_trace_on;
2297                         hr_utility.trace('sel ff_route_parameters TMR');
2298                         hr_utility.trace('parameter_name  ' ||
2299                           delivered_params.parameter_name);
2300                         hr_utility.trace('route_id  ' ||
2301                           to_char(l_new_surrogate_key));
2302                         hr_utility.trace('route_name  ' ||
2303                           stu_rec.c_true_key);
2304                         hr_utility.trace('sequence_no  ' ||
2305                           to_char(delivered_params.sequence_no));
2306                         hr_legislation.hrrunprc_trace_off;
2307                         raise;
2308 
2309 	    END; --select of new surrogate id
2310 
2311 	    update hr_s_route_parameters
2312 	    set    route_id = l_new_surrogate_key
2313 	    ,      route_parameter_id = l_new_parameter_id
2314 	    where  route_parameter_id = delivered_params.route_parameter_id;
2315 
2316 	    update hr_s_route_parameter_values
2317 	    set    route_parameter_id = l_new_parameter_id
2318             where  route_parameter_id = delivered_params.route_parameter_id;
2319 
2320         END LOOP delivered_params;
2321 
2322 	FOR delivered_entities IN user_entity(stu_Rec.c_Surrogate_key) LOOP
2323 
2324             BEGIN
2325 
2326 		select user_entity_id
2327 		into   l_new_entity_id
2328 	  	from   ff_user_entities
2329 	   	where  user_entity_name = delivered_entities.user_entity_name
2330                 and    nvl(legislation_code,'X') = nvl(delivered_entities.legislation_code,'X')
2331 	   	and    route_id = l_new_surrogate_key;
2332 
2333 	    EXCEPTION WHEN NO_DATA_FOUND THEN
2334 
2335 		select ff_user_entities_s.nextval
2336 		into   l_new_entity_id
2337 		from   dual;
2338 
2339                 WHEN TOO_MANY_ROWS THEN
2340                         hr_legislation.hrrunprc_trace_on;
2341                         hr_utility.trace('sel ff_user_entities TMR');
2342                         hr_utility.trace('user_entity_name  ' ||
2343                           delivered_entities.user_entity_name);
2344                         hr_utility.trace('route_id  ' ||
2345                           to_char(l_new_surrogate_key));
2346                         hr_utility.trace('route_name  ' ||
2347                           stu_rec.c_true_key);
2348                         hr_utility.trace(':lc: ' || ':' ||
2349                           delivered_entities.legislation_code || ':');
2353 
2350                         hr_legislation.hrrunprc_trace_off;
2351                         raise;
2352 	    END;
2354 	     update hr_s_user_entities
2355 	     set    user_entity_id = l_new_entity_id
2356 	     ,      route_id = l_new_surrogate_key
2357 	     where  user_entity_id = delivered_entities.user_entity_id;
2358 
2359 	     update hr_s_database_items
2360 	     set    user_entity_id = l_new_entity_id
2361              where  user_entity_id = delivered_entities.user_entity_id;
2362 
2363 	     update hr_s_route_parameter_values
2364              set    user_entity_id = l_new_entity_id
2365              where  user_entity_id = delivered_entities.user_entity_id;
2366 
2367   	     update hr_s_report_format_items_f
2368              set    user_entity_id = l_new_entity_id
2369              where  user_entity_id = delivered_entities.user_entity_id;
2370 
2371 	END LOOP;
2372 
2373     END update_uid;
2374 
2375     PROCEDURE remove (v_route_id IN number)
2376     ---------------------------------------
2377     IS
2378 	-- Remove a row from the startup tables
2379 
2380     BEGIN
2381 
2382    	delete from hr_s_database_items a
2383         where  a.user_entity_id in
2384           (select b.user_entity_id
2385            from   hr_s_user_entities b
2386            where  b.route_id = v_route_id
2387            );
2388 
2389    	delete from hr_s_route_parameter_values a
2390    	where  a.user_entity_id in
2391           (select b.user_entity_id
2392            from   hr_s_user_entities b
2393            where  b.route_id = v_route_id
2394            );
2395 
2396    	delete from hr_s_user_entities
2397    	where  route_id = v_route_id;
2398 
2399    	delete from hr_s_route_context_usages
2400    	where  route_id = v_route_id;
2401 
2402    	delete from hr_s_route_parameters
2403    	where  route_id = v_route_id;
2404 
2405    	delete from hr_s_routes
2406    	where  route_id = v_route_id;
2407 
2408     END remove;
2409 
2410     FUNCTION valid_ownership RETURN BOOLEAN
2411     ---------------------------------------
2412     IS
2413 	-- Test ownership of this current row
2414        cursor get_application_ownerships is
2415        select null
2416        from   dual
2417        where  exists
2418                (select null
2419                from   hr_s_application_ownerships a
2420                ,      fnd_product_installations b
2421                ,      fnd_application c
2422                where  a.key_name = 'ROUTE_ID'
2423                and    a.key_value = stu_rec.c_surrogate_key
2424                and    a.product_name = c.application_short_name
2425                and    c.application_id = b.application_id
2426                and    ((b.status = 'I' and c.application_short_name <> 'PQP')
2427                        or
2428                        (b.status in ('I', 'S') and c.application_short_name = 'PQP')));
2429     --
2430     BEGIN
2431 
2432 	-- This routine only operates in phase 1. Rows are present in the
2433 	-- table hr_application_ownerships in the delivery account, which
2434 	-- dictate which products a piece of data is used for. If the query
2435 	-- returns a row then this data is required, and the function will
2436 	-- return true. If no rows are returned and an exception is raised,
2437 	-- then this row is not required and may be deleted from the delivery
2438 	-- tables.
2439 
2440 	-- If legislation code and subgroup code are included on the delivery
2441 	-- tables, a check must be made to determine if the data is defined for
2442 	-- a specific subgroup. If so the subgroup must be 'A'ctive for this
2443 	-- installation.
2444 
2445 	-- A return code of TRUE indicates that the row is required.
2446 
2447 	-- The exception is raised within this procedure if no rows are returned
2448 	-- in this select statement. If no rows are returned then one of the
2449 	-- following is true:
2450 	--     1. No ownership parameters are defined.
2451 	--     2. The products, for which owning parameters are defined, are not
2452 	--        installed with as status of 'I'.
2453 	--     3. The data is defined for a legislation subgroup that is not active.
2454 
2455 	IF p_phase <> 1 THEN	-- Only perform in phase 1
2456 		return TRUE;
2457 	END IF;
2458 
2459 
2460 	-- If exception raised below then this row is not needed
2461         --
2462         open get_application_ownerships;
2463         fetch get_application_ownerships into l_null_return;
2464            IF get_application_ownerships%NOTFOUND OR get_application_ownerships%NOTFOUND IS NULL THEN
2465                RAISE NO_DATA_FOUND;
2466            END IF;
2467         close get_application_ownerships;
2468         --
2469 	-- Indicate row is required
2470 
2471    	return TRUE;
2472 
2473     EXCEPTION WHEN NO_DATA_FOUND THEN
2474 
2475 	-- Row not needed for any installed product
2476 
2477 	remove(stu_Rec.c_surrogate_key);
2478 
2479 	-- Indicate row not needed
2480 
2481 	return FALSE;
2482 
2483     END valid_ownership;
2484 
2485 
2486     FUNCTION route_changed (p_route_id IN number,
2487                             p_new_route OUT nocopy boolean) RETURN BOOLEAN
2488     ------------------------------------------------------------
2489     IS
2493 	-- Changed the comparison rules so that the routes are now only
2490 	-- Function to test if the current route is different to the one
2491 	-- installed. If the route is different the function will return true.
2492 	--
2494 	-- flagged as different if the route text itself has changed. In the
2495 	-- past the routes were also considered to be different if the last
2496 	-- update dates were differed. Unfortunately this was the case whenever
2497 	-- a dump file was recreated, even though the route text was unchanged.
2498 	-- This led to all routes being trashed and recreated on the target
2499 	-- account, db items being lost etc. RMF 26.09.95.
2500 	--
2501         -- Optimizer hint now can trigger update
2502 
2503        v_route_text long; 	-- Used to select the installed route text
2504        v_optimizer_hint ff_routes.optimizer_hint%type;
2505        v_last_update date;      -- Used to select the installed last update
2506 
2507     BEGIN
2508 
2509    	select text, optimizer_hint
2510    	into   v_route_text, v_optimizer_hint
2511    	from   ff_routes
2512    	where  route_id = p_route_id;
2513 
2514    	IF  v_route_text = stu_rec.text AND
2515             nvl(v_optimizer_hint, 'nohint') =
2516               nvl(stu_rec.optimizer_hint, 'nohint') THEN
2517 	    -- Route text and hint is identical
2518 	    return FALSE;
2519         END IF;
2520 
2521         p_new_route := FALSE;
2522 --        hr_legislation.hrrunprc_trace_on;
2523 --        hr_utility.trace('route diff: ' || to_char(l_new_surrogate_key) || ' '
2524 --                         || stu_rec.c_true_key);
2525 --        hr_legislation.hrrunprc_trace_off;
2526 
2527 	return TRUE; --delivered route is defferent
2528 
2529     EXCEPTION WHEN NO_DATA_FOUND THEN
2530 	-- The route is not installed
2531         p_new_route := TRUE;
2532 --        hr_legislation.hrrunprc_trace_on;
2533 --        hr_utility.trace('new route: ' || to_char(l_new_surrogate_key) || ' '
2534 --                         || stu_rec.c_true_key);
2535 --        hr_legislation.hrrunprc_trace_off;
2536 	return TRUE;
2537 
2538     END;
2539 
2540     FUNCTION valid_to_insert RETURN BOOLEAN
2541     ---------------------------------------
2542     IS
2543 	-- Check to see if the route can be installed.
2544     --
2545     l_number number(9);
2546     --
2547 
2548     BEGIN
2549 	-- Test to see if the route has been created already by a user. The
2550 	-- function will return true if the route is okay to be installed.
2551 
2552         --
2553    	select count(*)
2554    	into   l_number
2555    	from   ff_routes a
2556    	where  a.route_name = stu_rec.c_true_key
2557    	and    a.user_defined_flag = 'Y';
2558         --
2559 	if l_number = 0 or l_number is null then
2560    	   return TRUE;
2561         else
2562 	   --This Route name is an existing User-Defined route
2563 	   --So cannot be delivered.
2564    	   crt_exc('FF_Routes row already created by a user');
2565 	   return FALSE;--indicates this row is not to be transferred
2566         end if;
2567 
2568     EXCEPTION WHEN NO_DATA_FOUND THEN
2569 
2570 
2571 	-- No user created row exists for this primary key
2572 
2573 	return TRUE;
2574 
2575     END valid_to_insert;
2576 
2577     FUNCTION user_entity_changed (v_user_entity_id IN number) RETURN BOOLEAN
2578     ------------------------------------------------------------------------
2579     IS
2580 	-- Check to see if the current user entity differs from the install one
2581 	-- TRUE is returned if the user entity differs
2582 
2583     ue_name1 varchar2(240);
2584     ue_name2 varchar2(240);
2585 
2586     BEGIN
2587 
2588           select null
2589           into   l_null_return
2590           from   dual
2591           where  exists
2592             ((select
2593                      BUSINESS_GROUP_ID,
2594                      LEGISLATION_CODE,
2595                      ROUTE_ID,
2596                      NOTFOUND_ALLOWED_FLAG,
2597                      USER_ENTITY_NAME,
2598                      CREATOR_ID,
2599                      CREATOR_TYPE,
2600                      ENTITY_DESCRIPTION
2601               from   hr_s_user_entities
2602               where  user_entity_id = v_user_entity_id
2603   MINUS
2604               select
2605                      BUSINESS_GROUP_ID,
2606                      LEGISLATION_CODE,
2607                      ROUTE_ID,
2608                      NOTFOUND_ALLOWED_FLAG,
2609                      USER_ENTITY_NAME,
2610                      CREATOR_ID,
2611                      CREATOR_TYPE,
2612                      ENTITY_DESCRIPTION
2613               from   ff_user_entities
2614               where  user_entity_id = v_user_entity_id
2615   )
2616               UNION
2617              (select
2618                      BUSINESS_GROUP_ID,
2619                      LEGISLATION_CODE,
2620                      ROUTE_ID,
2621                      NOTFOUND_ALLOWED_FLAG,
2622                      USER_ENTITY_NAME,
2623                      CREATOR_ID,
2624                      CREATOR_TYPE,
2625                      ENTITY_DESCRIPTION
2626               from   ff_user_entities
2627               where  user_entity_id = v_user_entity_id
2628   MINUS
2629               select
2633                      NOTFOUND_ALLOWED_FLAG,
2630                      BUSINESS_GROUP_ID,
2631                      LEGISLATION_CODE,
2632                      ROUTE_ID,
2634                      USER_ENTITY_NAME,
2635                      CREATOR_ID,
2636                      CREATOR_TYPE,
2637                      ENTITY_DESCRIPTION
2638               from   hr_s_user_entities
2639               where  user_entity_id = v_user_entity_id
2640               ))
2641         or exists
2642                (select user_name,
2643                        data_type,
2644                        definition_text,
2645                        null_allowed_flag,
2646                        description
2647                 from   hr_s_database_items
2648                 where  user_entity_id = v_user_entity_id
2649                 MINUS
2650                 select user_name,
2651                        data_type,
2652                        definition_text,
2653                        null_allowed_flag,
2654                        description
2655                 from   ff_database_items
2656                 where  user_entity_id = v_user_entity_id)
2657          or exists
2658                 (select value
2659                  from   hr_s_route_parameter_values
2660                  where  user_entity_id = v_user_entity_id
2661                  MINUS
2662                  select value
2663                  from   ff_route_parameter_values
2664                  where  user_entity_id = v_user_entity_id);
2665 
2666         -- Show that this user entity differs from the install one
2667         begin
2668           select user_entity_name
2669           into   ue_name1
2670           from ff_user_entities
2671           where user_entity_id = v_user_entity_id;
2672           select user_entity_name
2673           into   ue_name2
2674           from hr_s_user_entities
2675           where user_entity_id = v_user_entity_id;
2676 --        hr_legislation.hrrunprc_trace_on;
2677 --        hr_utility.trace('ue chg: ' || to_char(v_user_entity_id) || ' '
2678 --                         || ue_name1 || ':' || ue_name2);
2679 --        hr_legislation.hrrunprc_trace_off;
2680         exception when others then null;
2681         end;
2682 
2683 	return TRUE;
2684 
2685     EXCEPTION WHEN NO_DATA_FOUND THEN
2686 
2687 
2688 	return FALSE;
2689 
2690     END user_entity_changed;
2691 
2692     FUNCTION install_user_entity (v_route_id IN number) RETURN BOOLEAN
2693     ------------------------------------------------------------------
2694     IS
2695 	-- Logic to insert the user entity and all children. If called in pahse one
2696 	-- TRUE is returned as soon as a user entity is found that has to be installed.
2697 	-- If no user entities are to be installed then FALSE is returned.
2698 
2699     cursor c_form(p_ue_id number) is
2700       select distinct fue.formula_id fid
2701       from   ff_fdi_usages_f fue
2702       where  fue.item_name in (select fdbi.user_name
2703                                from   ff_database_items fdbi
2704                                where  fdbi.user_entity_id = p_ue_id);
2705 
2706     BEGIN
2707 
2708 	FOR all_user_entities IN user_entity(v_route_id) LOOP
2709 
2710 
2711 	    IF user_entity_changed(all_user_entities.user_entity_id) THEN
2712 
2713                 IF p_phase = 1 THEN
2714 		    return TRUE;
2715 		END IF;
2716 
2717                 -- delete all formula usages, compiled info that may be
2718                 -- affected by this dbi
2719                 for r_form in c_form(all_user_entities.user_entity_id) loop
2720                   delete ff_fdi_usages_f where formula_id = r_form.fid;
2721                   delete ff_compiled_info_f where formula_id = r_form.fid;
2722                 end loop;
2723 
2724                 update ff_user_entities
2725                 set business_group_id = all_user_entities.business_group_id
2726                    ,legislation_code = all_user_entities.legislation_code
2727                    ,route_id = all_user_entities.route_id
2728                    ,notfound_allowed_flag = all_user_entities.notfound_allowed_flag
2729                    ,user_entity_name = all_user_entities.user_entity_name
2730                    ,creator_id = all_user_entities.creator_id
2731                    ,creator_type = all_user_entities.creator_type
2732                    ,entity_description = all_user_entities.entity_description
2733                    ,last_update_date = all_user_entities.last_update_date
2734                    ,last_updated_by = all_user_entities.last_updated_by
2735                    ,last_update_login = all_user_entities.last_update_login
2736                    ,created_by = all_user_entities.created_by
2737                    ,creation_date = all_user_entities.creation_date
2738                 where user_entity_id = all_user_entities.user_entity_id;
2739 
2740                 IF SQL%NOTFOUND THEN
2741 
2742                 BEGIN
2743 	   	insert into ff_user_entities
2744 	   	(user_entity_id
2745 	   	,business_group_id
2746 	   	,legislation_code
2747 	   	,route_id
2748 	   	,notfound_allowed_flag
2749 	   	,user_entity_name
2750 	   	,creator_id
2751 	   	,creator_type
2752 	   	,entity_description
2753 	   	,last_update_date
2754 	   	,last_updated_by
2755 	  	,last_update_login
2756 	  	,created_by
2757 	   	,creation_date
2758 	   	)
2762 	   	,all_user_entities.legislation_code
2759 	   	values
2760 	   	(all_user_entities.user_entity_id
2761 	   	,all_user_entities.business_group_id
2763 	   	,all_user_entities.route_id
2764 		,all_user_entities.notfound_allowed_flag
2765 	   	,all_user_entities.user_entity_name
2766 	   	,all_user_entities.creator_id
2767 	  	,all_user_entities.creator_type
2768 	   	,all_user_entities.entity_description
2769 	   	,all_user_entities.last_update_date
2770 	   	,all_user_entities.last_updated_by
2771 	   	,all_user_entities.last_update_login
2772 	  	,all_user_entities.created_by
2773 	   	,all_user_entities.creation_date
2774 	   	);
2775 
2776                       EXCEPTION WHEN OTHERS THEN
2777                         hr_legislation.hrrunprc_trace_on;
2778                         hr_utility.trace('ins ff_user_entities');
2779                         hr_utility.trace('user_entity_name  ' ||
2780                           all_user_entities.user_entity_name);
2781                         hr_utility.trace('user_entity_id  ' ||
2782                           to_char(all_user_entities.user_entity_id));
2783                         hr_utility.trace('route_id  ' ||
2784                           to_char(all_user_entities.route_id));
2785                         hr_utility.trace('route_name  ' ||
2786                           stu_rec.c_true_key);
2787                         hr_utility.trace('creator_id  ' ||
2788                           to_char(all_user_entities.creator_id));
2789                         hr_utility.trace('creator_type  ' ||
2790                           all_user_entities.creator_type);
2791                         hr_utility.trace(':lc: ' || ':' ||
2792                           all_user_entities.legislation_code || ':');
2793                         hr_legislation.hrrunprc_trace_off;
2794                         raise;
2795                       END;
2796                 END IF;
2797 
2798 	   	FOR all_db_items IN
2799 		  db_item(all_user_entities.user_entity_id)
2800 		LOOP
2801 
2802                     update ff_database_items
2803                     set    data_type = all_db_items.data_type
2804                           ,definition_text = all_db_items.definition_text
2805                           ,null_allowed_flag = all_db_items.null_allowed_flag
2806                           ,description = all_db_items.description
2807                           ,last_update_date = all_db_items.last_update_date
2808                           ,last_updated_by = all_db_items.last_updated_by
2809                           ,last_update_login = all_db_items.last_update_login
2810                           ,created_by = all_db_items.created_by
2811                           ,creation_date = all_db_items.creation_date
2812                     where user_name = all_db_items.user_name
2813                     and   user_entity_id = all_db_items.user_entity_id;
2814 
2815                     IF SQL%NOTFOUND THEN
2816 
2817                     BEGIN
2818 		    insert into ff_database_items
2819 		    (user_name
2820 		    ,user_entity_id
2821 		    ,data_type
2822 		    ,definition_text
2823 		    ,null_allowed_flag
2824 		    ,description
2825 		    ,last_update_date
2826 		    ,last_updated_by
2827 		    ,last_update_login
2828 		    ,created_by
2829 		    ,creation_date
2830 		    )
2831 		    VALUES
2832 		    (all_db_items.user_name
2833 		    ,all_db_items.user_entity_id
2834 		    ,all_db_items.data_type
2835 		    ,all_db_items.definition_text
2836 		    ,all_db_items.null_allowed_flag
2837 		    ,all_db_items.description
2838 		    ,all_db_items.last_update_date
2839 		    ,all_db_items.last_updated_by
2840 		    ,all_db_items.last_update_login
2841 		    ,all_db_items.created_by
2842 		    ,all_db_items.creation_date
2843 		    );
2844                       EXCEPTION WHEN OTHERS THEN
2845                         hr_legislation.hrrunprc_trace_on;
2846                         hr_utility.trace('ins ff_database_items');
2847                         hr_utility.trace('dbi user_name  ' ||
2848                           all_db_items.user_name);
2849                         hr_utility.trace('user_entity_id  ' ||
2850                           to_char(all_db_items.user_entity_id));
2851                         hr_utility.trace('user_entity_name  ' ||
2852                           all_user_entities.user_entity_name);
2853                         hr_utility.trace('route_id  ' ||
2854                           to_char(all_user_entities.route_id));
2855                         hr_utility.trace('route_name  ' ||
2856                           stu_rec.c_true_key);
2857                         hr_utility.trace('creator_id  ' ||
2858                           to_char(all_user_entities.creator_id));
2859                         hr_utility.trace('creator_type  ' ||
2860                           all_user_entities.creator_type);
2861                         hr_legislation.hrrunprc_trace_off;
2862                         raise;
2863                       END;
2864 
2865                     END IF;
2866 
2867 		END LOOP all_db_items;
2868 
2869 		FOR pvalues IN
2870 		  parameter_value(all_user_entities.user_entity_id)
2871 		LOOP
2872 
2873 		    BEGIN
2874 
2875                     update ff_route_parameter_values
2876                     set    value = pvalues.value
2880                           ,created_by = pvalues.created_by
2877                           ,last_update_date = pvalues.last_update_date
2878                           ,last_updated_by = pvalues.last_updated_by
2879                           ,last_update_login = pvalues.last_update_login
2881                           ,creation_date = pvalues.creation_date
2882                     where route_parameter_id = pvalues.route_parameter_id
2883                     and   user_entity_id = pvalues.user_entity_id;
2884 
2885                     IF SQL%NOTFOUND THEN
2886 
2887                     BEGIN
2888 		    insert into ff_route_parameter_values
2889 		   	(route_parameter_id
2890 		   	,user_entity_id
2891 		   	,value
2892 		   	,last_update_date
2893 		   	,last_updated_by
2894 		  	,last_update_login
2895 		   	,created_by
2896 		   	,creation_date
2897 		   	)
2898 		   	VALUES
2899 		   	(pvalues.route_parameter_id
2900 		  	,pvalues.user_entity_id
2901 		   	,pvalues.value
2902 		   	,pvalues.last_update_date
2903 		   	,pvalues.last_updated_by
2904 		   	,pvalues.last_update_login
2905 		   	,pvalues.created_by
2906 		   	,pvalues.creation_date
2907 		   	);
2908                       EXCEPTION WHEN OTHERS THEN
2909                         hr_legislation.hrrunprc_trace_on;
2910                         hr_utility.trace('ins ff_route_parameter_values');
2911                         hr_utility.trace('value  ' ||
2912                           pvalues.value);
2913                         hr_utility.trace('route_parameter_id  ' ||
2914                           to_char(pvalues.route_parameter_id));
2915                         hr_utility.trace('user_entity_id  ' ||
2916                           to_char(pvalues.user_entity_id));
2917                         hr_utility.trace('user_entity_name  ' ||
2918                           all_user_entities.user_entity_name);
2919                         hr_utility.trace('route_id  ' ||
2920                           to_char(all_user_entities.route_id));
2921                         hr_utility.trace('route_name  ' ||
2922                           stu_rec.c_true_key);
2923                         hr_utility.trace('creator_id  ' ||
2924                           to_char(all_user_entities.creator_id));
2925                         hr_utility.trace('creator_type  ' ||
2926                           all_user_entities.creator_type);
2927                         hr_legislation.hrrunprc_trace_off;
2928                         raise;
2929                       END;
2930 
2931                      END IF;
2932 
2933 		    END;
2934 
2935 	       END LOOP pvalues;
2936 
2937 
2938 	    END IF;
2939 
2940        END LOOP all_user_entities;
2941 
2942        IF p_phase = 1 THEN
2943            return FALSE;
2944        ELSE
2945            return TRUE;
2946        END IF;
2947 
2948     END install_user_entity;
2949 
2950     PROCEDURE delete_route_form_usage
2951     ---------------------------------
2952     IS
2953 
2954     cursor c_form2(p_route_id number) is
2955       select /*+ INDEX(ffu FF_FDI_USAGES_F_N50)*/
2956              distinct ffu.formula_id fid
2957       from   ff_fdi_usages_f ffu
2958       where  ffu.item_name in (select fdbi.user_name
2959                                from   ff_database_items fdbi,
2960                                       ff_user_entities fue,
2961                                       ff_routes fr
2962                                where  fdbi.user_entity_id = fue.user_entity_id
2963                                and    fue.route_id = fr.route_id
2964                                and    fr.route_id = p_route_id);
2965 
2966     BEGIN
2967         -- delete all formula usages, compiled info that may be
2968         -- affected by this dbi
2969         for r_form2 in c_form2(stu_rec.c_surrogate_key) loop
2970 
2971            delete ff_fdi_usages_f where formula_id = r_form2.fid;
2972            delete ff_compiled_info_f where formula_id = r_form2.fid;
2973         end loop;
2974 
2975     END delete_route_form_usage;
2976 
2977     PROCEDURE insert_route
2978     ----------------------
2979     IS
2980 	-- Logic to insert or update a route, depending upon whether it exists
2981 	-- already in the live tables
2982 
2983     BEGIN
2984 
2985 	update ff_routes
2986 	set user_defined_flag = stu_rec.user_defined_flag
2987 	,   description = stu_Rec.description
2988 	,   text  = stu_rec.text
2989 	,   last_update_date = stu_rec.last_update_date
2990 	,   last_updated_by = stu_rec.last_updated_by
2991 	,   last_update_login = stu_rec.last_update_login
2992 	,   created_by = stu_rec.created_by
2993 	,   creation_date = stu_rec.creation_date
2994         ,   optimizer_hint = stu_rec.optimizer_hint
2995 	where  route_id = stu_rec.c_Surrogate_key;
2996 
2997 	IF SQL%NOTFOUND THEN
2998 
2999             BEGIN
3000 	    insert into ff_Routes
3001 	    (route_id
3002 	    ,route_name
3003 	    ,user_defined_flag
3004 	    ,description
3005 	    ,text
3006 	    ,last_update_date
3007 	    ,last_updated_by
3008 	    ,last_update_login
3009 	    ,created_by
3010 	    ,creation_date
3011             ,optimizer_hint
3012 	    )
3013 	    values
3014 	    (stu_rec.c_surrogate_key
3015 	    ,stu_rec.c_true_key
3019 	    ,stu_rec.last_update_date
3016 	    ,stu_rec.user_defined_flag
3017 	    ,stu_rec.description
3018 	    ,stu_rec.text
3020 	    ,stu_rec.last_updated_by
3021 	    ,stu_rec.last_update_login
3022 	    ,stu_rec.created_by
3023 	    ,stu_rec.creation_date
3024             ,stu_rec.optimizer_hint
3025 	    );
3026                       EXCEPTION WHEN OTHERS THEN
3027                         hr_legislation.hrrunprc_trace_on;
3028                         hr_utility.trace('ins ff_routes');
3029                         hr_utility.trace('route_name  ' ||
3030                           stu_rec.c_true_key);
3031                         hr_utility.trace('route_id  ' ||
3032                           to_char(stu_rec.c_surrogate_key));
3033                         hr_legislation.hrrunprc_trace_off;
3034                         raise;
3035                       END;
3036 
3037 	END IF;
3038 
3039     END insert_route;
3040 
3041     PROCEDURE transfer_row
3042     ----------------------
3043     IS
3044        -- Procedure to transfer a route from the delivery tables
3045        cursor c_ff_contexts_null (c_context_id in number) is
3046        select null
3047        from   ff_contexts
3048        where  context_id = c_context_id;
3049        --
3050        cursor c_ffrp_null (c_route_parameter_id in number) is
3051        select null
3052        from   ff_route_parameters
3053        where  route_parameter_id = c_route_parameter_id;
3054        --
3055        cursor c_ff_rcu_pop (c_route_id in number,
3056                             c_sequence_no in number,
3057                             c_context_id in number) is
3058        select distinct null
3059        from   ff_route_context_usages
3060        where  route_id = c_route_id
3061        and    sequence_no = c_sequence_no
3062        and    context_id = c_context_id;
3063        --
3064     BEGIN
3065         --
3066 	IF p_phase = 1 THEN
3067 	    IF route_changed(l_new_surrogate_key, l_new_route) THEN
3068 		IF NOT valid_to_insert THEN
3069 		    return;
3070 		END IF;
3071 	    ELSE
3072 		-- Route has not changed, check user entities
3073 
3074 	        IF install_user_entity(l_new_surrogate_key) THEN
3075 	            null;
3076 		ELSE
3077 		    -- No user entities to install
3078                     remove(l_new_surrogate_key);
3079 	      	    return;
3080 	        END IF;
3081 	    END IF;
3082 	ELSE
3083 	    -- Phase = 2
3084 	    IF route_changed(stu_rec.c_surrogate_key, l_new_route) THEN
3085                 --
3086 		IF NOT valid_to_insert THEN
3087 		    return;
3088 		END IF;
3089 		delete_route_form_usage;
3090 		insert_route;
3091                 --
3092                 -- Ensure we rebuild all balance user entities and associated
3093                 -- items in rebuild ele input bal for a changed route
3094                 --
3095                 IF NOT l_new_route THEN
3096                     delete from ff_user_entities
3097                     where creator_type in ('B', 'RB')
3098                     and route_id = stu_rec.c_surrogate_key;
3099                 END IF;
3100                 --
3101                 -- Changing or inserting route so delete live ctx usages
3102                 -- for this route
3103                 --
3104                 delete ff_route_context_usages
3105                 where  route_id = stu_rec.c_surrogate_key;
3106                 --
3107                 -- Now install route ctx usages
3108                 --
3109 		FOR context_usages IN usage(stu_rec.c_surrogate_key) LOOP
3110 
3111 		    BEGIN
3112                        --
3113                        open c_ff_contexts_null (context_usages.context_id);
3114                        fetch c_ff_contexts_null into l_null_return;
3115                        IF c_ff_contexts_null%NOTFOUND OR c_ff_contexts_null%NOTFOUND IS NULL THEN
3116                           close c_ff_contexts_null;
3117                           RAISE NO_DATA_FOUND;
3118                        END IF;
3119                        close c_ff_contexts_null;
3120                        --
3121                         BEGIN
3122                         insert into ff_route_context_usages
3123                         (route_id
3124                         ,context_id
3125                         ,sequence_no
3126                         )
3127                         values
3128                         (context_usages.route_id
3129                         ,context_usages.context_id
3130                         ,context_usages.sequence_no
3131                         );
3132                        EXCEPTION WHEN OTHERS THEN
3133                         hr_legislation.hrrunprc_trace_on;
3134                         hr_utility.trace('ins ff_route_context_usages');
3135                         hr_utility.trace('route_id  ' ||
3136                           to_char(context_usages.route_id));
3137                         hr_utility.trace('route_name  ' ||
3138                           stu_rec.c_true_key);
3139                         hr_utility.trace('context_id  ' ||
3140                           to_char(context_usages.context_id));
3141                         hr_utility.trace('sequence_no  ' ||
3142                           to_char(context_usages.sequence_no));
3146 
3143                         hr_legislation.hrrunprc_trace_off;
3144                         raise;
3145                       END;
3147 		    EXCEPTION WHEN NO_DATA_FOUND THEN
3148 
3149 		    	crt_exc('Parent context not installed');
3150 		    	return;
3151 		    END;
3152 	    	END LOOP;
3153 
3154                 FOR r_hrsrp in parameter (stu_rec.c_surrogate_key) LOOP
3155 
3156                   BEGIN
3157 
3158                        open c_ffrp_null (r_hrsrp.ROUTE_PARAMETER_ID);
3159                        fetch c_ffrp_null into l_null_return;
3160                        IF c_ffrp_null%NOTFOUND OR c_ffrp_null%NOTFOUND IS NULL THEN
3161                                 close c_ffrp_null;
3162                                 RAISE NO_DATA_FOUND;
3163                        END IF;
3164                        close c_ffrp_null;
3165 
3166                   update ff_route_parameters
3167                   set    ROUTE_ID = stu_rec.c_surrogate_key
3168                         ,DATA_TYPE = r_hrsrp.DATA_TYPE
3169                         ,PARAMETER_NAME = r_hrsrp.PARAMETER_NAME
3170                         ,SEQUENCE_NO = r_hrsrp.SEQUENCE_NO
3171                   where ROUTE_PARAMETER_ID = r_hrsrp.ROUTE_PARAMETER_ID;
3172 
3173                   EXCEPTION WHEN NO_DATA_FOUND THEN
3174 
3175                   BEGIN
3176    	    	  insert into ff_route_parameters
3177               	  (ROUTE_PARAMETER_ID
3178              	  ,ROUTE_ID
3179             	  ,DATA_TYPE
3180             	  ,PARAMETER_NAME
3181               	  ,SEQUENCE_NO
3182             	  )
3183                   values
3184                   (r_hrsrp.ROUTE_PARAMETER_ID,
3185                    stu_rec.c_surrogate_key,
3186                    r_hrsrp.DATA_TYPE,
3187                    r_hrsrp.PARAMETER_NAME,
3188                    r_hrsrp.SEQUENCE_NO);
3189                       EXCEPTION WHEN OTHERS THEN
3190                         hr_legislation.hrrunprc_trace_on;
3191                         hr_utility.trace('ins ff_route_parameters');
3192                         hr_utility.trace('PARAMETER_NAME  ' ||
3193                           r_hrsrp.PARAMETER_NAME);
3194                         hr_utility.trace('SEQUENCE_NO  ' ||
3195                           to_char(r_hrsrp.SEQUENCE_NO));
3196                         hr_utility.trace('ROUTE_ID  ' ||
3197                           to_char(stu_rec.c_surrogate_key));
3198                         hr_utility.trace('route_name  ' ||
3199                           stu_rec.c_true_key);
3200                         hr_utility.trace('ROUTE_PARAMETER_ID ' ||
3201                           to_char(r_hrsrp.ROUTE_PARAMETER_ID));
3202                         hr_legislation.hrrunprc_trace_off;
3203                         raise;
3204                       END;
3205 
3206                   END;
3207 
3208                 END LOOP;
3209 
3210 	    END IF;
3211             --
3212 	    IF NOT install_user_entity(stu_rec.c_surrogate_key) THEN
3213 	    	return;
3214 	    END IF;
3215 	    remove(stu_rec.c_surrogate_key);
3216         END IF;
3217 
3218     END transfer_row;
3219 
3220 BEGIN
3221     -- This is the main loop to perform the installation logic. A cursor
3222     -- is opened to control the loop, and each row returned is placed
3223     -- into a record defined within the main procedure so each sub
3224     -- procedure has full access to all returrned columns. For each
3225     -- new row returned, a new savepoint is declared. If at any time
3226     -- the row is in error a rollback iss performed to the savepoint
3227     -- and the next row is returned. Ownership details are checked and
3228     -- if the row is required then the surrogate id is updated and the
3229     -- main transfer logic is called.
3230 
3231     -- Need to disable the UE constraint so we can update user entities
3232     -- outside of the main transfer process so we dont lose our savepoints
3233     -- via implicit commits
3234 
3235 --    disable_ffuebru_trig;
3236 
3237     IF p_phase = 1 THEN
3238 	check_id_conflicts; --attempt to detect and remove any possible
3239 			    --conflicts with surrogate id's that are being
3240 			    --delivered.
3241 
3242     END IF;
3243 
3244     FOR delivered IN stu LOOP
3245 
3246 	-- This uses main cursor stu to impilicity define a record
3247 
3248 
3249         savepoint new_route_name;
3250 
3251         stu_rec := delivered;
3252 
3253         IF p_phase = 2 THEN
3254 	    l_new_surrogate_key := stu_rec.c_surrogate_key;
3255 	END IF;
3256 
3257         IF valid_ownership THEN
3258 
3259 	    -- Test the row onerships for the current row
3260 
3261 
3262 	    IF p_phase = 1 THEN
3263                 update_uid;
3264 	    END IF;
3265 
3266 	    transfer_row;
3267 
3268         END IF;
3269 
3270     END LOOP delivered;
3271 
3272 --    enable_ffuebru_trig;
3273 
3274 END install_routes;
3275 
3276 
3277 --****************************************************************************
3278 -- INSTALLATION PROCEDURE FOR : FF_FUNCTIONS
3279 --****************************************************************************
3280 
3281 PROCEDURE install_functions(p_phase IN number)
3282 ----------------------------------------------
3283 IS
3287     -- The installation of functions is controlled by a main cursor which
3284     -- Install procedure to transfer startup element classifications into
3285     -- a live account.
3286 
3288     -- selects distinct function names from the startup tables.
3289 
3290     -- For each of these function names if the installed functions differ to the
3291     -- delivered ones, all installed functions of this name will refreshed.
3292 
3293     l_null_return varchar2(1); 		-- For 'select null' statements
3294     l_new_surrogate_key number(15); 	-- New surrogate key for the delivery row
3295 
3296     CURSOR stu				-- Selects all rows from startup entity
3297     IS
3298    	select distinct name
3299    	,      legislation_code c_leg_code
3300    	from   hr_s_functions;
3301 
3302     CURSOR distinct_function(f_name IN varchar2, c_leg_code IN varchar2)
3303     IS
3304 	-- Cursor to select distinct functions
3305 
3306    	select *
3307    	from   hr_s_functions
3308    	where  name = f_name
3309         and    nvl(legislation_code, 'X') = nvl(c_leg_code, 'X');
3310 
3311     CURSOR usages(f_id IN number)
3312     IS
3313 	-- Cursor to install child context usages
3314 
3315    	select *
3316    	from   hr_s_function_context_usages
3317    	where  function_id = f_id;
3318 
3319     stu_rec stu%ROWTYPE;
3320 
3321     PROCEDURE crt_exc (exception_type IN varchar2)
3322     ----------------------------------------------
3323     IS
3324 	-- Reports any exceptions during the delivery of startup data to
3325 	-- FF_FUNCTIONS
3326 
3327     BEGIN
3328 	-- When the installation procedures encounter an error that cannot
3329 	-- be handled, an exception is raised and all work is rolled back
3330 	-- to the last savepoint. The installation process then continues
3331 	-- with the next primary key to install. The same exception will
3332 	-- not be raised more than once.
3333 
3334 	-- The exception text is set to a composite value because this exception
3335 	-- is raised against a function name, not a function id. Consequently
3336 	-- the surrogate id is set to a value of 0.
3337 
3338 
3339 	rollback to new_function_name;
3340 
3341 	hr_legislation.insert_hr_stu_exceptions('ff_functions'
3342         ,      0
3343         ,      exception_type
3344         ,      stu_rec.name);
3345 
3346 
3347     END crt_exc;
3348 
3349     PROCEDURE remove(target varchar2)
3350     ---------------------------------
3351     IS
3352 	-- Remove a row from either the startup tables or the installed tables
3353 
3354     BEGIN
3355 	-- This procedure either deletes from the delivered account,
3356    	-- parameter of 'D', or from the live account, parameter of 'I'.
3357 
3358    	-- If the delivered details are being deleted the explicit deletes
3359    	-- from all child tables are required, since the cascade constraint
3360    	-- will not be delivered with these tables.
3361 
3362    	-- When deleting from the live account, the cascade delete can
3363    	-- be relied upon.
3364 
3365         IF target = 'D' THEN
3366 
3367 	    delete from hr_s_function_context_usages a
3368 	    where  exists
3369 		   (select null
3370 		   from   hr_s_functions b
3371 		   where  b.function_id = a.function_id
3372 		   and    b.name = stu_rec.name
3373                    and nvl(b.legislation_code,'X')=nvl(stu_rec.c_leg_code,'X')
3374 		   );
3375 
3376 	    delete from hr_s_function_parameters a
3377 	    where  exists
3378 		   (select null
3379 		   from   hr_s_functions b
3380 		   where  b.function_id = a.function_id
3381 		   and    b.name = stu_rec.name
3382                    and nvl(b.legislation_code,'X')=nvl(stu_rec.c_leg_code,'X')
3383 		   );
3384 
3385 
3386 	    delete from hr_s_functions
3387 	    where  name = stu_rec.name
3388             and    nvl(legislation_code,'X')=nvl(stu_rec.c_leg_code,'X');
3389 
3390 	ELSE
3391 
3392 	    -- Delete from live account using the cascade delete
3393 
3394 
3395 	    delete from ff_functions
3396 	    where  name = stu_rec.name
3397             and    nvl(legislation_code,'X')=nvl(stu_rec.c_leg_code,'X');
3398 
3399 	END IF;
3400 
3401     END remove;
3402 
3403     PROCEDURE insert_delivered
3404     --------------------------
3405     IS
3406 	-- Check if a delivered row is needed and insert into the
3407 	-- live tables if it is
3408 
3409 	v_inst_update date;  	-- Holds update details of installed row
3410 
3411     BEGIN
3412 
3413 
3414 	BEGIN
3415 
3416 	    -- Perform a check to see if the primary key has been created within
3417 	    -- a visible business group. Ie: the business group is for the same
3418 	    -- legislation as the delivered row, or the delivered row has a null
3419 	    -- legislation. If no rows are returned then the primary key has not
3420 	    -- already been created by a user.
3421 
3422             select distinct null
3423             into   l_null_return
3424             from ff_functions a
3425             where a.name = stu_rec.name
3426             and   a.business_group_id is not null
3427             and   exists (select null from per_business_groups b
3428               where b.business_group_id = a.business_group_id
3432 
3429               and b.legislation_code = nvl(stu_rec.c_leg_code,b.legislation_code));
3430 
3431             crt_exc('Row already created in a business group');
3433 	    -- Indicate this row is not to be transferred
3434 
3435             return;
3436 
3437  	EXCEPTION WHEN NO_DATA_FOUND THEN
3438 
3439 	    null;
3440 
3441 	END;
3442 
3443 
3444 	-- Now perform a check to see if this primary key has been installed
3445 	-- with a legislation code that would make it visible at the same time
3446 	-- as this row. Ie: if any legislation code is null within the set of
3447 	-- returned rows, then the transfer may not go ahead. If no rows are
3448 	-- returned then the delivered row is fine.
3449 
3450 	BEGIN
3451             select distinct null
3452             into   l_null_return
3453             from   ff_functions
3454             where  name = stu_rec.name
3455             and    nvl(legislation_code,'X') <> nvl(stu_rec.c_leg_code,'X')
3456             and   (
3457                    legislation_code is null
3458                 or stu_rec.c_leg_code is null
3459                    );
3460 
3461             crt_exc('Row already created for a visible legislation');
3462 
3463 	    -- Indicates this row is not to be transferred
3464 
3465             return;
3466 
3467    	EXCEPTION WHEN NO_DATA_FOUND THEN
3468 
3469 	    null;
3470 
3471 	END;
3472 
3473 
3474 	-- This procedure is only called in phase 2. All matching live
3475 	-- functions will be be deleted and replaced with the delivered
3476 	-- rows.
3477 
3478 	-- The routine check_parents validates foreign key references and
3479 	-- ensures referential integrity. The routine checks to see if the
3480 	-- parents of a given row have been transfered to the live tables.
3481 
3482 	-- This may only be called in phase two since in phase one all
3483 	-- parent rows will remain in the delivery tables.
3484 
3485 	-- After the above checks only data that has been chanegd or is new
3486 	-- will be left in the delivery tables.
3487 
3488 	-- The last step of this transfer, in phase 2, is to delete the now
3489 	-- transfered row from the delivery tables.
3490 
3491 	-- Before the update/insert goes ahead, ensure all child rows
3492 	-- are removed so the refrsh of child rows is simple.
3493 
3494 	remove('I');
3495 
3496 	FOR each_func IN distinct_function(stu_rec.name, stu_rec.c_leg_code) LOOP
3497 
3498 
3499 	    select ff_functions_s.nextval
3500 	    into   l_new_surrogate_key
3501 	    from   dual;
3502 
3503 
3504  BEGIN
3505 	    insert into ff_functions
3506 	    (function_id
3507 	    ,business_group_id
3508 	    ,legislation_code
3509 	    ,class
3510 	    ,name
3511 	    ,alias_name
3512 	    ,data_type
3513 	    ,definition
3514 	    ,last_update_date
3515 	    ,last_updated_by
3516 	    ,last_update_login
3517 	    ,created_by
3518 	    ,creation_date
3519 	    )
3520 	    values (l_new_surrogate_key
3521 	    ,null
3522 	    ,each_func.legislation_code
3523 	    ,each_func.class
3524 	    ,each_func.name
3525 	    ,each_func.alias_name
3526 	    ,each_func.data_type
3527 	    ,each_func.definition
3528 	    ,each_func.last_update_date
3529 	    ,each_func.last_updated_by
3530 	    ,each_func.last_update_login
3531 	    ,each_func.created_by
3532 	    ,each_func.creation_date
3533 	    );
3534 
3535 
3536                      EXCEPTION WHEN OTHERS THEN
3537                         hr_legislation.hrrunprc_trace_on;
3538                         hr_utility.trace('ins ff_functions');
3539                         hr_utility.trace('function name  ' ||
3540                           each_func.name);
3541                         hr_utility.trace('function_id  ' ||
3542                           to_char(l_new_surrogate_key));
3543                         hr_utility.trace(':lc: ' || ':' ||
3544                           each_func.legislation_code || ':');
3545                         hr_legislation.hrrunprc_trace_off;
3546                         raise;
3547                       END;
3548 
3549             BEGIN
3550             insert into ff_function_parameters
3551 	    (function_id
3552 	    ,sequence_number
3553 	    ,class
3554 	    ,continuing_parameter
3555 	    ,data_type
3556 	    ,name
3557 	    ,optional
3558 	    )
3559 	    select l_new_surrogate_key
3560 	    ,      sequence_number
3561 	    ,      class
3562 	    ,      continuing_parameter
3563 	    ,      data_type
3564 	    ,      name
3565 	    ,      optional
3566 	    from   hr_s_function_parameters
3567 	    where  function_id = each_func.function_id;
3568                       EXCEPTION WHEN OTHERS THEN
3569                         hr_legislation.hrrunprc_trace_on;
3570                         hr_utility.trace('ins ff_function_parameters');
3571                         hr_utility.trace('function_id  ' ||
3572                           to_char(each_func.function_id));
3573                         hr_utility.trace('function name  ' ||
3574                           each_func.name);
3578                         raise;
3575                         hr_utility.trace(':lc: ' ||
3576                           each_func.legislation_code || ':');
3577                         hr_legislation.hrrunprc_trace_off;
3579                       END;
3580 
3581 	    FOR child_usages IN usages(each_func.function_id) LOOP
3582 
3583 	        BEGIN
3584 
3585 
3586 		    select null
3587 		    into   l_null_return
3588 		    from   ff_contexts
3589 		    where  context_id = child_usages.context_id;
3590 
3591 		    insert into ff_function_context_usages
3592 		    (function_id
3593 		    ,sequence_number
3594 		    ,context_id
3595 		    )
3596 		    values
3597 		    (l_new_surrogate_key
3598 		    ,child_usages.sequence_number
3599 		    ,child_usages.context_id
3600 		    );
3601 
3602 	        EXCEPTION WHEN NO_DATA_FOUND THEN
3603 
3604 
3605 		    crt_exc('Context referenced by child usage is not present');
3606 
3607 		    return;
3608 
3609                     WHEN OTHERS THEN
3610                         hr_legislation.hrrunprc_trace_on;
3611                         hr_utility.trace('ins ff_function_context_usages');
3612                         hr_utility.trace('function_id  ' ||
3613                           to_char(l_new_surrogate_key));
3614                         hr_utility.trace('function name  ' ||
3615                           each_func.name);
3616                         hr_utility.trace(':lc: ' ||
3617                           each_func.legislation_code || ':');
3618                         hr_utility.trace('sequence_number  ' ||
3619                           to_char(child_usages.sequence_number));
3620                         hr_utility.trace('context_id  ' ||
3621                           to_char(child_usages.context_id));
3622                         hr_legislation.hrrunprc_trace_off;
3623                         raise;
3624 
3625 	        END;
3626 
3627 	    END LOOP child_usages;
3628 
3629         END LOOP each_func;
3630 
3631 
3632         remove('D');
3633 
3634     END insert_delivered;
3635 
3636 BEGIN
3637     -- This is the main loop to perform the installation logic. A cursor
3638     -- is opened to control the loop, and each row returned is placed
3639     -- into a record defined within the main procedure so each sub
3640     -- procedure has full access to all returrned columns. For each
3641     -- new row returned, a new savepoint is declared. If at any time
3642     -- the row is in error a rollback is performed to the savepoint
3643     -- and the next row is returned.
3644 
3645     -- In phase 1 the only logic is to check if the function needs to be
3646     -- installed. If the function needs to be installed, it will be left
3647     -- in the delivery tables. If not then it will be deleted.
3648 
3649     -- The surrogate id will be created/set in phase 2.
3650 
3651     -- In phase 2 all installed functions of the name stu_rec.name will be
3652     -- deleted from the live account. All delivered functions/usages/parameters
3653     -- will be then inserted. At this point a new function id will be allocated.
3654 
3655     FOR delivered IN stu LOOP
3656 
3657 	-- Uses main cursor stu to impilicity define a record
3658 
3659 
3660 	savepoint new_function_name;
3661 
3662    	stu_rec := delivered;
3663 
3664 
3665 	IF p_phase = 2 THEN
3666 	  insert_delivered;
3667 	END IF;
3668 
3669     END LOOP;
3670 
3671 END install_functions;
3672 
3673 --****************************************************************************
3674 -- INSTALLATION PROCEDURE FOR : FF_QP_REPORTS
3675 --****************************************************************************
3676 
3677 PROCEDURE install_qpreports(p_phase IN number)
3678 ----------------------------------------------
3679 IS
3680     -- Install procedure to transfer startup QuickPaint reports into
3681     -- a live account.
3682 
3683     l_null_return varchar2(1);		-- For 'select null' statements
3684     l_new_surrogate_key number(15); 	-- New surrogate key for the delivery row
3685 
3686     CURSOR stu				-- Selects all rows from startup entity
3687     IS
3688 
3689 	select qp_report_id c_surrogate_key
3690 	,      formula_id
3691 	,      formula_type_id
3692 	,      qp_report_name c_true_key
3693 	,      business_group_id
3694 	,      legislation_code c_leg_code
3695 	,      qp_altered_formula
3696 	,      qp_description
3697 	,      qp_text
3698 	,      last_update_date
3699 	,      last_updated_by
3700 	,      last_update_login
3701 	,      created_by
3702 	,      creation_date
3703 	,      rowid
3704 	from   hr_s_qp_reports;
3705 
3706     stu_rec stu%ROWTYPE;
3707 
3708     PROCEDURE crt_exc(exception_type IN varchar2)
3709     ---------------------------------------------
3710     IS
3711 	-- If an exception has been detected meaning that the delivered row may
3712 	-- not be installed, then it must be reported
3713 
3714     BEGIN
3715 
3716 	-- When the installation procedures encounter an error that cannot
3717 	-- be handled, an exception is raised and all work is rolled back
3718 	-- to the last savepoint. The installation process then continues
3722 
3719 	-- with the next primary key to install. The same exception will
3720 	-- not be raised more than once.
3721 
3723 	rollback to new_qp_report_name;
3724 
3725 	hr_legislation.insert_hr_stu_exceptions('ff_qp_reports'
3726         ,      stu_rec.c_surrogate_key
3727         ,      exception_type
3728         ,      stu_rec.c_true_key);
3729 
3730 
3731     END crt_exc;
3732 
3733     PROCEDURE check_next_sequence
3734     -----------------------------
3735     IS
3736 
3737    	v_sequence_number number(9);
3738    	v_min_delivered number(9);
3739    	v_max_delivered number(9);
3740 
3741 	-- Surrogate id conflicts may arise from two scenario's:
3742 	-- 1. Where the newly select sequence value conflicts with values
3743 	--    in the STU tables.
3744 	-- 2. Where selected surrogate keys, from the installed tables,
3745 	--    conflict with other rows in the STU tables.
3746 	--
3747 	-- Both of the above scenario's are tested for.
3748 	-- The first is a simple match, where if a value is detected in the
3749 	-- STU tables and the installed tables then a conflict is detected. In
3750 	-- This instance all STU surrogate keys, for this table, are updated.
3751 	-- The second is tested for using the sequences.
3752 	-- If the next value from the live sequence is within the range of
3753 	-- delivered surrogate id's then the live sequence must be incremented.
3754 	-- If no action is taken, then duplicates may be introduced into the
3755 	-- delivered tables, and child rows may be totally invalidated.
3756 
3757     BEGIN
3758 
3759 
3760 	BEGIN	--check that the installed id's will not conflict
3761 		--with the delivered values
3762 
3763 
3764 	    select distinct null
3765 	    into   l_null_return
3766 	    from   ff_qp_reports a
3767 	    where  exists
3768 		(select null
3769 		 from   hr_s_qp_reports b
3770 		 where  a.qp_report_id = b.qp_report_id
3771 		);
3772 
3773 	    --conflict may exist
3774 	    --update all qp_report_id's to remove conflict
3775 
3776 	    update hr_s_qp_reports
3777 	    set    qp_report_id = qp_report_id - 50000000;
3778 
3779 	    update hr_s_application_ownerships
3780 	    set    key_value = key_value - 50000000
3781 	    where  key_name = 'QP_REPORT_ID';
3782 
3783 	EXCEPTION WHEN NO_DATA_FOUND THEN NULL;
3784 
3785 	END; --check of qp_report_id
3786 
3787 
3788 	select min(qp_report_id) - (count(*) *3)
3789    	,      max(qp_report_id) + (count(*) *3)
3790    	into   v_min_delivered
3791    	,      v_max_delivered
3792    	from   hr_s_qp_reports;
3793 
3794    	select ff_qp_reports_s.nextval
3795    	into   v_sequence_number
3796    	from   dual;
3797 
3798    	IF v_sequence_number
3799 	  BETWEEN v_min_delivered AND v_max_delivered THEN
3800 
3801             hr_legislation.munge_sequence('FF_QP_REPORTS_S',
3802                                           v_sequence_number,
3803                                           v_max_delivered);
3804 
3805         END IF;
3806 
3807     END check_next_sequence;
3808 
3809     PROCEDURE update_uid
3810     --------------------
3811     IS
3812 	-- Update surrogate UID and all occurrences in child rows
3813 
3814     BEGIN
3815 
3816 
3817 	BEGIN
3818 
3819 	    select distinct qp_report_id
3820 	    into   l_new_surrogate_key
3821 	    from   ff_qp_reports
3822 	    where  qp_report_name = stu_rec.c_true_key
3823 	    and    business_group_id is null
3824             and  ( (legislation_code is null and stu_rec.c_leg_code is null)
3825                 or (legislation_code = stu_rec.c_leg_code) );
3826 
3827     	EXCEPTION WHEN NO_DATA_FOUND THEN
3828 
3829 	    select ff_qp_reports_s.nextval
3830 	    into   l_new_surrogate_key
3831 	    from   dual;
3832 
3833 	END;
3834 
3835 	-- Update all child entities
3836 
3837    	update hr_s_qp_reports
3838         set    qp_report_id = l_new_surrogate_key
3839     	where  qp_report_id = stu_rec.c_surrogate_key;
3840 
3841    	update hr_s_application_ownerships
3842    	set    key_value = to_char(l_new_surrogate_key)
3843    	where  key_value = to_char(stu_rec.c_surrogate_key)
3844    	and    key_name = 'QP_REPORT_ID';
3845 
3846     END update_uid;
3847 
3848     PROCEDURE remove
3849     ----------------
3850     IS
3851 	-- Remove a row from either the startup tables or the installed tables
3852 
3853     BEGIN
3854 
3855    	delete from hr_s_qp_reports
3856    	where  rowid = stu_rec.rowid;
3857 
3858     END remove;
3859 
3860     FUNCTION valid_ownership RETURN BOOLEAN
3861     ---------------------------------------
3862     IS
3863 	-- Test ownership of this current row
3864 
3865 	-- This routine only operates in phase 1. Rows are present in the
3866 	-- table hr_application_ownerships in the delivery account, which
3867 	-- dictate which products a piece of data is used for. If the query
3868 	-- returns a row then this data is required, and the function will
3869 	-- return true. If no rows are returned and an exception is raised,
3870 	-- then this row is not required and may be deleted from the delivery
3871 	-- tables.
3872 
3876 	-- installation.
3873 	-- If legislation code and subgroup code are included on the delivery
3874 	-- tables, a check must be made to determine if the data is defined for
3875 	-- a specific subgroup. If so the subgroup must be 'A'ctive for this
3877 
3878 	-- A return code of TRUE indicates that thhe row is required.
3879 
3880 	-- The exception is raised within this procedure if no rows are returned
3881 	-- in this select statement. If no rows are returned then one of the
3882 	-- following is true:
3883 	--     1. No ownership parameters are defined.
3884 	--     2. The products, for which owning parameters are defined, are not
3885 	--        installed with as status of 'I'.
3886 	--     3. The data is defined for a legislation subgroup that is not active.
3887 
3888     BEGIN
3889 
3890 
3891 	IF p_phase <> 1 THEN	-- Only perform in phase 1
3892 		return TRUE;
3893 	END IF;
3894 
3895 
3896 	-- If exception raised below then this row is not needed
3897         -- get rid of subgrp table, not even using it!
3898 	select null
3899 	into   l_null_return
3900 	from   dual
3901 	where  exists
3902 	   (select null
3903 	    from   hr_s_application_ownerships a
3904 	    ,      fnd_product_installations b
3905 	    ,      fnd_application c
3906 	    where  a.key_name = 'QP_REPORT_ID'
3907 	    and    a.key_value = stu_rec.c_surrogate_key
3908 	    and    a.product_name = c.application_short_name
3909 	    and    c.application_id = b.application_id
3910             and    ((b.status = 'I' and c.application_short_name <> 'PQP')
3911                     or
3912                     (b.status in ('I', 'S') and c.application_short_name = 'PQP')));
3913 
3914 	-- Indicates row is required
3915 
3916 	return TRUE;
3917 
3918     EXCEPTION WHEN NO_DATA_FOUND THEN
3919 
3920 	-- Row not needed for any installed product
3921 
3922 
3923         remove;
3924 
3925 	-- Indicate row not needed
3926 
3927 	return FALSE;
3928 
3929     END valid_ownership;
3930 
3931     FUNCTION check_parents RETURN BOOLEAN
3932     -------------------------------------
3933     IS
3934 	-- Check if parent data is correct
3935 
3936 	-- This procedure is only called in phase 2. The logic to check if
3937 	-- a given parental foriegn key exists is split into two parts for
3938 	-- every foriegn key. The first select from the delivery tables.
3939 
3940 	-- If a row is founnd then the installation of the parent must have
3941 	-- failed, and this installation must not go ahead. If no data is
3942 	-- found, ie: an exception is raised, the installation is valid.
3943 
3944 	-- The second check looks for a row in the live tables. If no rows
3945 	-- are returned then this installation is invalid, since this means
3946 	-- that the parent referenced by this row is not present in the
3947 	-- live tables.
3948 
3949 	-- The distinct is used in case the parent is date effective and many rows
3950 	-- may be returned by the same parent id.
3951 
3952     BEGIN
3953 
3954 	-- Start parent checking against formula types
3955 
3956 
3957 	BEGIN
3958 
3959 	    -- Checking the delivery account
3960 
3961 	    select distinct null
3962 	    into   l_null_return
3963 	    from   hr_s_formula_types
3964 	    where  formula_type_id = stu_rec.formula_type_id;
3965 
3966 	    crt_exc('Parent formula type remains in delivery tables');
3967 
3968 	    -- Parent row still in startup account
3969 
3970 	    return FALSE;
3971 
3972 	EXCEPTION WHEN NO_DATA_FOUND THEN
3973 
3974 	    null;
3975 
3976 	END;
3977 
3978 
3979 	BEGIN
3980 
3981 	    -- Checking the installed account
3982 
3983 	    select null
3984 	    into   l_null_return
3985 	    from   ff_formula_types
3986 	    where  formula_type_id = stu_rec.formula_type_id;
3987 
3988 	    -- Drop down to second parent check
3989 
3990    	EXCEPTION WHEN NO_DATA_FOUND THEN
3991 
3992 
3993 	    crt_exc('Parent formula type not installed');
3994 
3995 	    return FALSE;
3996 
3997 	END;
3998 
3999         -- Start parent checking against formulas
4000 
4001 
4002 	BEGIN
4003 
4004 	    -- Checking the delivery account
4005 
4006             select distinct null
4007             into   l_null_return
4008             from   hr_s_formulas_f
4009             where  formula_id = stu_rec.formula_id;
4010 
4011             crt_exc('Parent formula remains in delivery tables');
4012 
4013 	    -- Parent row still in startup account
4014 
4015             return FALSE;
4016 
4017 	EXCEPTION WHEN NO_DATA_FOUND THEN
4018 
4019 	    null;
4020 
4021 	END;
4022 
4023 
4024 	BEGIN
4025 
4026 	    -- Checking the installed account
4027 
4028             select distinct null
4029             into   l_null_return
4030             from   ff_formulas_f
4031             where  formula_id = stu_rec.formula_id;
4032 
4033             return TRUE;
4034 
4035        EXCEPTION WHEN NO_DATA_FOUND THEN
4036 
4037 
4038            crt_exc('Parent formula not installed');
4039 
4043 
4040            return FALSE;
4041 
4042 	END;
4044     END check_parents;
4045 
4046     PROCEDURE transfer_row
4047     ----------------------
4048     IS
4049 	-- Check if a delivered row is needed and insert into the
4050 	-- live tables if it is
4051 
4052 	v_inst_update date;	-- Holds update details of installed row
4053 
4054     BEGIN
4055 
4056 
4057 	BEGIN
4058 
4059 	    -- Perform a check to see if the primary key has been created
4060 	    -- within a visible business group. Ie: the business group
4061 	    -- is for the same legislation as the delivered row, or the
4062 	    -- delivered row has a null legislation. If no rows are
4063 	    -- returned then the primary key has not already been
4064 	    -- created by a user.
4065 
4066             select distinct null
4067             into   l_null_return
4068             from ff_qp_reports a
4069             where a.qp_report_name = stu_rec.c_true_key
4070             and   a.business_group_id is not null
4071             and   exists (select null from per_business_groups b
4072               where b.business_group_id = a.business_group_id
4073               and b.legislation_code = nvl(stu_rec.c_leg_code,b.legislation_code));
4074 
4075             crt_exc('Row already created in a business group');
4076 
4077 	    -- Indicate this row is not to be transferred
4078 
4079 	    return;
4080 
4081 	EXCEPTION WHEN NO_DATA_FOUND THEN
4082 
4083 	    null;
4084 
4085 	END;
4086 
4087 
4088 	-- Now perform a check to see if this primary key has been installed
4089 	-- with a legislation code that would make it visible at the same time
4090 	-- as this row. Ie: if any legislation code is null within the set of
4091 	-- returned rows, then the transfer may not go ahead. If no rows are
4092 	-- returned then the delivered row is fine.
4093 
4094 	BEGIN
4095 
4096 	    select distinct null
4097             into   l_null_return
4098             from   ff_qp_reports
4099             where  qp_report_name = stu_rec.c_true_key
4100             and    nvl(legislation_code,'X') <> nvl(stu_rec.c_leg_code,'X')
4101             and   (legislation_code is null
4102 		   or stu_rec.c_leg_code is null );
4103 
4104 	    crt_exc('Row already created for a visible legislation');
4105 
4106 	    -- Indicate this row is not to be transferred
4107 
4108 	    return;
4109 
4110 	EXCEPTION WHEN NO_DATA_FOUND THEN
4111 
4112 	    null;
4113 
4114 	END;
4115 
4116 
4117 	-- When the procedure is called in phase 1, there is no need to
4118 	-- actually perform the transfer from the delivery tables into the
4119 	-- live. Hence if phase = 1 control is returned to the calling
4120 	-- procedure and the next row is returned.
4121 
4122 	-- If the procedure is called in phase 2, then the live row is updated
4123 	-- with the values on the delivered row.
4124 
4125 	-- The routine check_parents validates foreign key references and
4126 	-- ensures referential integrity. The routine checks to see if the
4127 	-- parents of a given row have been transfered to the live tables.
4128 
4129 	-- This may only be called in phase two since in phase one all
4130 	-- parent rows will remain in the delivery tables.
4131 
4132 	-- After the above checks only data that has been chanegd or is new
4133 	-- will be left in the delivery tables. At this stage if the row is
4134 	-- already present then it must be updated to ensure referential
4135 	-- integrity. Therefore an update will be performed and if SQL%FOUND
4136 	-- is FALSE an insert will be performed.
4137 
4138 	-- The last step of the transfer, in phase 2, is to delete the now
4139 	-- transfered row from the delivery tables.
4140 
4141 	IF p_phase = 1 THEN
4142 	    return;
4143 	END IF;
4144 
4145 	IF NOT check_parents THEN
4146 	    -- Fails because parents exist
4147 	    return;
4148 	END IF;
4149 
4150 
4151    	update ff_qp_reports
4152    	set    formula_id = stu_rec.formula_id
4153    	,      formula_type_id = stu_rec.formula_type_id
4154    	,      qp_report_name = to_char(stu_rec.c_surrogate_key)
4155    	,      business_group_id = null
4156    	,      legislation_code = stu_rec.c_leg_code
4157    	,      qp_altered_formula = stu_rec.qp_altered_formula
4158    	,      qp_description = stu_rec.qp_description
4159    	,      qp_text = stu_rec.qp_text
4160    	,      last_update_date = stu_rec.last_update_date
4161    	,      last_updated_by = stu_rec.last_updated_by
4162    	,      last_update_login = stu_rec.last_update_login
4163    	,      created_by = stu_rec.created_by
4164    	,      creation_date = stu_rec.creation_date
4165    	where  qp_report_id = stu_rec.c_surrogate_key;
4166 
4167    	IF NOT SQL%FOUND THEN
4168 
4169 
4170 	    insert into ff_qp_reports
4171 	    (qp_report_id
4172 	    ,formula_id
4173 	    ,formula_type_id
4174 	    ,qp_report_name
4175 	    ,business_group_id
4176 	    ,legislation_code
4177 	    ,qp_altered_formula
4178 	    ,qp_description
4179 	    ,qp_text
4180 	    ,last_update_date
4181 	    ,last_updated_by
4182 	    ,last_update_login
4183 	    ,created_by
4184 	    ,creation_date
4185 	    )
4186 	    values
4190 	    ,stu_rec.c_true_key
4187 	    (stu_rec.c_surrogate_key
4188 	    ,stu_rec.formula_id
4189 	    ,stu_rec.formula_type_id
4191 	    ,null
4192 	    ,stu_rec.c_leg_code
4193 	    ,stu_rec.qp_altered_formula
4194 	    ,stu_rec.qp_description
4195 	    ,stu_rec.qp_text
4196 	    ,stu_rec.last_update_date
4197 	    ,stu_rec.last_updated_by
4198 	    ,stu_rec.last_update_login
4199 	    ,stu_rec.created_bY
4200 	    ,stu_rec.creation_date
4201 	    );
4202 
4203 	END IF;
4204 
4205 
4206         remove;
4207 
4208     END transfer_row;
4209 
4210 BEGIN
4211     -- This is the main loop to perform the installation logic. A cursor
4212     -- is opened to control the loop, and each row returned is placed
4213     -- into a record defined within the main procedure so each sub
4214     -- procedure has full access to all returrned columns. For each
4215     -- new row returned, a new savepoint is declared. If at any time
4216     -- the row is in error a rollback iss performed to the savepoint
4217     -- and the next row is returned. Ownership details are checked and
4218     -- if the row is required then the surrogate id is updated and the
4219     -- main transfer logic is called.
4220 
4221     IF p_phase = 1 THEN
4222 	check_next_sequence;
4223     END IF;
4224 
4225     FOR delivered IN stu LOOP
4226 
4227 	-- Uses main cursor stu to impilicity define a record
4228 
4229 
4230 	savepoint new_qp_report_name;
4231 
4232    	stu_rec := delivered;
4233 
4234 	IF p_phase = 2 THEN
4235 	    l_new_surrogate_key := stu_rec.c_surrogate_key;
4236 	END IF;
4237 
4238 	IF valid_ownership THEN
4239 
4240 	    -- Test the row ownerships for the current row
4241 
4242 
4243 	    IF p_phase = 1 THEN
4244 		update_uid;
4245 	    END IF;
4246 
4247 	    transfer_row;
4248 
4249 	END IF;
4250 
4251     END LOOP;
4252 
4253 END install_qpreports;
4254 
4255 --****************************************************************************
4256 -- INSTALLATION PROCEDURE FOR : FF_GLOBALS_S
4257 --****************************************************************************
4258 
4259 PROCEDURE install_globals(p_phase IN NUMBER)
4260 --------------------------------------------
4261 IS
4262     -- Install procedure to transfer startup delivered globals into a
4263     -- live account, and remove the then delivered rows from the delivery
4264     -- account.
4265 
4266     -- This procedure is called in two phase. Only in the second phase are
4267     -- details transferred into live tables. The parameter p_phase holds
4268     -- the phase number.
4269 
4270     row_in_error exception;
4271     l_current_proc varchar2(80) := 'hr_legislation.install_globals';
4272     l_new_global_id number(15);
4273     l_null_return varchar2(1);
4274     status varchar2(10);
4275 
4276     CURSOR c_distinct
4277     IS
4278 	-- Select statement used for the main loop. Each row return is used
4279 	-- as the commit unit, since each true primary key may have many date
4280 	-- effective rows for it.
4281 
4282 	-- The selected primary key is then passed into the second driving
4283 	-- cursor statement as a parameter, and all date effective rows for
4284 	-- this primary key are then selected.
4285 
4286   	select max(effective_end_date) c_end
4287 	,      global_id c_surrogate_key
4288    	,      global_name c_true_key
4289    	,      legislation_code
4290    	from   hr_s_globals_f
4291    	group  by global_id
4292    	,         global_name
4293    	,         legislation_code;
4294 
4295     CURSOR c_each_row(pc_global_id varchar2)
4296     IS
4297 	-- Selects all date effective rows for the current true primary key
4298 	-- The primary key has already been selected using the above cursor.
4299 	-- This cursor accepts the primary key as a parameter and selects all
4300 	-- date effective rows for it.
4301 
4302 	select *
4303 	from   hr_s_globals_f
4304 	where  global_id = pc_global_id;
4305 
4306     -- These records are defined here so all sub procedures may use the
4307     -- values selected. This saves the need for all sub procedures to have
4308     -- a myriad of parameters passed. The cursors are controlled in FOR
4309     -- cursor LOOPs. When a row is returned the whole record is copied into
4310     -- these record definitions.
4311 
4312     CURSOR c_global_ad(p_global_id number)
4313     IS
4314       -- This cursor is used when deleting rows from ff_globals_f.
4315       -- FF_GLOBAL_F has an after delete trigger that removes user_entities
4316       -- that have a creator_id = the global_id of the row being removed.
4317       -- When deleting these UE, the BRD UE trigger potentially deletes
4318       -- database items. This trigger invalidates all formulae that can be
4319       -- affected by these dbi removals.
4320       select distinct ffu.formula_id fid
4321       from   ff_fdi_usages_f ffu
4322       where  ffu.item_name in (select fdbi.user_name
4323                                from   ff_database_items fdbi,
4324                                       ff_user_entities ffue
4325                                where  fdbi.user_entity_id = ffue.user_entity_id
4326                                  and  ffue.creator_id = p_global_id
4327                                  and  ffue.creator_type = 'S');
4328 
4332     PROCEDURE remove (v_id IN number)
4329     r_distinct c_distinct%ROWTYPE;
4330     r_each_row c_each_row%ROWTYPE;
4331 
4333     ---------------------------------
4334     IS
4335 	-- Subprogram to delete a row from the delivery tables, and all child
4336 	-- application ownership rows
4337 
4338     BEGIN
4339 
4340 
4341    	delete from hr_s_globals_f
4342    	where  global_id = v_id;
4343 
4344     END remove;
4345 
4346     PROCEDURE check_next_sequence
4347     -----------------------------
4348     IS
4349 
4350 	v_sequence_number number(9);
4351 	v_min_delivered number(9);
4352 	v_max_delivered number(9);
4353 
4354 	-- Surrogate id conflicts may arise from two scenario's:
4355 	-- 1. Where the newly select sequence value conflicts with values
4356 	--    in the STU tables.
4357 	-- 2. Where selected surrogate keys, from the installed tables,
4358 	--    conflict with other rows in the STU tables.
4359 	--
4360 	-- Both of the above scenario's are tested for.
4361 	-- The first is a simple match, where if a value is detected in the
4362 	-- STU tables and the installed tables then a conflict is detected. In
4363 	-- This instance all STU surrogate keys, for this table, are updated.
4364 	-- The second is tested for using the sequences.
4365 	-- If the next value from the live sequence is within the range of
4366 	-- delivered surrogate id's then the live sequence must be incremented.
4367 	-- If no action is taken, then duplicates may be introduced into the
4368 	-- delivered tables, and child rows may be totally invalidated.
4369 
4370     BEGIN
4371 
4372 
4373 	BEGIN	--check that the installed id's will not conflict
4374 		--with the delivered values
4375 
4376 
4377 	    select distinct null
4378 	    into   l_null_return
4379 	    from   ff_globals_f a
4380 	    where  exists
4381 		(select null
4382 		 from   hr_s_globals_f b
4383 		 where  a.global_id = b.global_id
4384 		);
4385 
4386 	    --conflict may exist
4387 	    --update all global_id's to remove conflict
4388 
4389 	    update /*+NO_INDEX*/ hr_s_globals_f
4390 	    set    global_id = global_id - 50000000;
4391 
4392 	    update hr_s_application_ownerships
4393 	    set    key_value = key_value - 50000000
4394 	    where  key_name = 'GLOBAL_ID';
4395 
4396 	EXCEPTION WHEN NO_DATA_FOUND THEN NULL;
4397 
4398 	END; --check of global_id
4399 
4400 
4401    	select min(global_id) - (count(*) *3)
4402    	,      max(global_id) + (count(*) *3)
4403    	into   v_min_delivered
4404    	,      v_max_delivered
4405    	from   hr_s_globals_f;
4406 
4407    	select ff_globals_s.nextval
4408    	into   v_sequence_number
4409    	from   dual;
4410 
4411         IF v_sequence_number
4412           BETWEEN v_min_delivered AND v_max_delivered THEN
4413 
4414             hr_legislation.munge_sequence('FF_GLOBALS_S',
4415                                           v_sequence_number,
4416                                           v_max_delivered);
4417         END IF;
4418 
4419     END check_next_sequence;
4420 
4421     PROCEDURE update_uid
4422     --------------------
4423     IS
4424 	-- Subprogram to update surrogate UID and all occurrences in child rows
4425 
4426     BEGIN
4427 
4428 	-- See if this primary key is already installed. If so then the sorrogate
4429 	-- key of the delivered row must be updated to the value in the installed
4430 	-- tables. If the row is not already present then select the next value
4431 	-- from the sequence. In either case all rows for this primary key must
4432 	-- be updated, as must all child references to the old surrogate uid.
4433 
4434 
4435 	BEGIN
4436 
4437 	    select distinct global_id
4438 	    into   l_new_global_id
4439 	    from   ff_globals_f
4440 	    where  global_name = r_distinct.c_true_key
4441 	    and    business_Group_id is null
4442             and    ((legislation_code is NULL and r_distinct.legislation_code is NULL)
4443                     or (r_distinct.legislation_code=legislation_code));
4444 
4445 
4446 	EXCEPTION WHEN NO_DATA_FOUND THEN
4447 
4448 
4449 	    select ff_globals_s.nextval
4450 	    into   l_new_global_id
4451 	    from   dual;
4452 
4453             WHEN TOO_MANY_ROWS THEN
4454                         hr_legislation.hrrunprc_trace_on;
4455                         hr_utility.trace('sel ff_globals_f TMR');
4456                         hr_utility.trace('global_name  ' ||
4457                           r_distinct.c_true_key);
4458                         hr_utility.trace(':lc: ' || ':' ||
4459                           r_distinct.legislation_code || ':');
4460                         hr_legislation.hrrunprc_trace_off;
4461                         raise;
4462 	END;
4463 
4464 	update hr_s_globals_f
4465    	set    global_id = l_new_global_id
4466    	where  global_id = r_distinct.c_surrogate_key;
4467 
4468    	update hr_s_application_ownerships
4469    	set    key_value = to_char(l_new_global_id)
4470    	where  key_value = to_char(r_distinct.c_surrogate_key)
4471    	and    key_name = 'GLOBAL_ID';
4472 
4473     END update_uid;
4474 
4475     PROCEDURE crt_exc(exception_type IN varchar2)
4476     ---------------------------------------------
4480 
4477     IS
4478 	-- If an exception has been detected meaning that the delivered row may
4479 	-- not be installed, then it must be reported
4481     BEGIN
4482 
4483 	-- When the installation procedures encounter an error that cannot
4484 	-- be handled, an exception is raised and all work is rolled back
4485 	-- to the last savepoint. The installation process then continues
4486 	-- with the next primary key to install. The same exception will
4487 	-- not be raised more than once.
4488 
4489    	rollback to new_global_name;
4490 
4491 	hr_legislation.insert_hr_stu_exceptions('ff_globals_f'
4492         ,      r_distinct.c_surrogate_key
4493         ,      exception_type
4494         ,      r_distinct.c_true_key);
4495 
4496 
4497     END crt_exc;
4498 
4499 -- ----------------------------------
4500 -- ----------------------------------
4501     FUNCTION valid_ownership RETURN BOOLEAN
4502     ---------------------------------------
4503     IS
4504 	-- Test ownership of this current row
4505 
4506 	-- This function is split into three distinct parts. The first
4507 	-- checks to see if a row exists with the same primary key, for a
4508 	-- business group that would have access to the delivered row. The
4509 	-- second checks details for data created in other legislations,
4510 	-- in case data is either created with a null legislation or the
4511 	-- delivered row has a null legislation. The last check examines
4512 	-- if this data is actually required for a given install by examining
4513 	-- the product installation table, and the ownership details for
4514 	-- this row.
4515 
4516 	-- A return code of TRUE indicates that the row is required.
4517         cursor get_ff_globals is
4518             select distinct null
4519             from ff_globals_f a
4520             where a.global_name = r_distinct.c_true_key
4521             and   a.business_group_id is not null
4522             and   exists (select null from per_business_groups b
4523               where b.business_group_id = a.business_group_id
4524               and b.legislation_code = nvl(r_distinct.legislation_code,b.legislation_code));
4525 
4526         --
4527         cursor c_valid_ownership is
4528             select distinct null
4529             from   ff_globals_f
4530             where  global_name = r_distinct.c_true_key
4531             and    nvl(legislation_code,'X')<>nvl(r_distinct.legislation_code,'X')
4532             and   (legislation_code is null
4533                    or r_distinct.legislation_code is null );
4534         --
4535 	BEGIN
4536    	    BEGIN
4537 		-- Perform a check to see if the primary key has been
4538 		-- created within a visible business group. Ie: the
4539 		-- business group is for the same legislation as the
4540 		-- delivered row, or the delivered row has a null
4541 		-- legislation. If no rows are returned then the primary
4542 		-- key has not already been created by a user.
4543 
4544                 open get_ff_globals;
4545                 fetch get_ff_globals into l_null_return;
4546                     IF get_ff_globals%NOTFOUND OR get_ff_globals%NOTFOUND IS NULL THEN
4547                         RAISE NO_DATA_FOUND;
4548                     END IF;
4549                 close get_ff_globals;
4550                 --
4551 		crt_exc('Row already created in a business group');
4552 		-- Indicate this row is not to be transferred
4553 		return FALSE;
4554 
4555 	     EXCEPTION WHEN NO_DATA_FOUND THEN
4556 		null;
4557             --
4558 	    END;
4559 
4560 	    -- Now perform a check to see if this primary key has been installed
4561 	    -- with a legislation code that would make it visible at the same time
4562 	    -- as this row. Ie: if any legislation code is null within the set of
4563 	    -- returned rows, then the transfer may not go ahead. If no rows are
4564 	    -- returned then the delivered row is fine.
4565 
4566 	BEGIN
4567             --
4568             open c_valid_ownership;
4569             fetch c_valid_ownership into l_null_return;
4570                 IF c_valid_ownership%NOTFOUND OR c_valid_ownership%NOTFOUND IS NULL THEN
4571                     RAISE NO_DATA_FOUND;
4572                 END IF;
4573             close c_valid_ownership;
4574             --
4575 	    crt_exc('Row already created for a visible legislation');
4576 	    return FALSE; --indicates this row is not to be transferred
4577 
4578 	EXCEPTION WHEN NO_DATA_FOUND THEN
4579 	    null;
4580 	END;
4581 
4582 	-- The last check examines the product installation table, and the
4583 	-- ownership details for the delivered row. By examining these
4584 	-- tables the row is either deleted or not. If the delivered row
4585 	-- is 'stamped' with a legislation subgroup, then a chweck must be
4586 	-- made to see if that subgroup is active or not. This check only
4587 	-- needs to be performed in phase 1, since once this decision is
4588 	-- made, it is pontless to perform this logic again.
4589 	-- in this select statement. If no rows are returned then one of the
4590 	-- following is true:
4591 	--     1. No ownership parameters are defined.
4592 	--     2. The products, for which owning parameters are defined, are not
4593 	--        installed with as status of 'I'.
4594 	--     3. The data is defined for a legislation subgroup that is not active.
4595 
4596 	IF p_phase <> 1 THEN return TRUE; END IF;
4597 
4598 
4602             where exists (select null from hr_s_application_ownerships a
4599 	    select null
4600 	    into   l_null_return
4601 	    from   dual
4603 	    ,      fnd_product_installations b
4604 	    ,      fnd_application c
4605 	    where  a.key_name = 'GLOBAL_ID'
4606 	    and    a.key_value = r_distinct.c_surrogate_key
4607 	    and    a.product_name = c.application_short_name
4608 	    and    c.application_id = b.application_id
4609             and    ((b.status = 'I' and c.application_short_name <> 'PQP')
4610                     or
4611                     (b.status in ('I', 'S') and c.application_short_name = 'PQP')));
4612 
4613 
4614 	    -- Indicate row is required
4615 
4616 	    return TRUE;
4617 
4618 	EXCEPTION WHEN NO_DATA_FOUND THEN
4619 
4620 	    -- Row not needed for any installed product
4621 
4622 
4623 	    remove(r_distinct.c_surrogate_key);
4624 
4625 	    -- Indicate row not needed
4626 
4627 	    return FALSE;
4628 
4629     END valid_ownership;
4630 
4631 BEGIN
4632     -- Two loops are used here. The main loop which select distinct primary
4633     -- key rows and an inner loop which selects all date effective rows for the
4634     -- primary key. The inner loop is only required in phase two, since only
4635     -- in phase 2 are rows actually transferred. The logic reads as follows:
4636 
4637     --    - Only deal with rows which have correct ownership details and will
4638     --      not cause integrity problems (valid_ownership).
4639 
4640     --    - In Phase 1:
4641     --               - Delete delivery rows where the installed rows are identicle.
4642     --               - The UNION satement compares delivery rows to installed rows.
4643     --                 If the sub query returns any rows, then the delivered
4644     --                 tables and the installed tables are different.
4645     --    - In Phase 2:
4646     --               - Delete from the installed tables using the surrogate id.
4647     --               - If an installed row is to be replaced, the values of
4648     --                 the surrogate keys will be identicle at this stage.
4649     --               - Data will then be deleted from the delivery tables.
4650     --               - Call the installation procedure for any child tables, that
4651     --                 must be installed within the same commit unit. If any
4652     --                 errors occur then rollback to the last declared savepoint.
4653     --               - Check that all integrity rules are still obeyed at the end
4654     --                 of the installation (validity_checks).
4655 
4656     -- An exception is used with this procedure 'row_in_error' in case an error
4657     -- is encountered from calling any function. If this is raised, then an
4658     -- exception is entered into the control tables (crt_exc();) and a rollback
4659     -- is performed.
4660 
4661 -- disable dynamic cont calc trigger
4662 -- dis_cont_calc_trigger;
4663 
4664     IF p_phase = 1 THEN
4665 	check_next_sequence;
4666     END IF;
4667 
4668     FOR primary_keys IN c_distinct LOOP
4669 
4670 	r_distinct := primary_keys;
4671 
4672 
4673    	savepoint new_global_name;
4674 
4675         BEGIN
4676 
4677 	    IF valid_ownership THEN
4678 
4682 		IF p_phase = 1 THEN
4679 	        -- This row is wanted
4680 
4681 
4683 
4684 
4685 		    -- Get new surrogate id and update child references
4686 
4687 		    update_uid;
4688 
4689 		    delete from hr_s_globals_f
4690 		    where  global_id = l_new_global_id
4691 		    and    not exists
4692 		           ((select
4693                                EFFECTIVE_START_DATE,
4694                                EFFECTIVE_END_DATE,
4695                                BUSINESS_GROUP_ID,
4696                                LEGISLATION_CODE,
4697                                DATA_TYPE,
4698                                GLOBAL_NAME,
4699                                GLOBAL_DESCRIPTION,
4700                                GLOBAL_VALUE
4701 			     from   hr_s_globals_f
4702 			     where  global_id = l_new_global_id
4703 			     MINUS
4704 			     select
4705                                EFFECTIVE_START_DATE,
4706                                EFFECTIVE_END_DATE,
4707                                BUSINESS_GROUP_ID,
4708                                LEGISLATION_CODE,
4709                                DATA_TYPE,
4710                                GLOBAL_NAME,
4711                                GLOBAL_DESCRIPTION,
4712                                GLOBAL_VALUE
4713                              from   ff_globals_f
4714 			     where  global_id = l_new_global_id
4715 			    )
4716 			     UNION
4717 			    (select
4718                                EFFECTIVE_START_DATE,
4719                                EFFECTIVE_END_DATE,
4720                                BUSINESS_GROUP_ID,
4721                                LEGISLATION_CODE,
4722                                DATA_TYPE,
4723                                GLOBAL_NAME,
4724                                GLOBAL_DESCRIPTION,
4725                                GLOBAL_VALUE
4726                              from   ff_globals_f
4727                              where  global_id = l_new_global_id
4728                              MINUS
4729                              select
4730                                EFFECTIVE_START_DATE,
4731                                EFFECTIVE_END_DATE,
4732                                BUSINESS_GROUP_ID,
4733                                LEGISLATION_CODE,
4734                                DATA_TYPE,
4735                                GLOBAL_NAME,
4736                                GLOBAL_DESCRIPTION,
4737                                GLOBAL_VALUE
4738                              from   hr_s_globals_f
4739                              where  global_id = l_new_global_id
4740 		           ))
4741                and exists (select distinct null
4742                    from   ff_user_entities u,
4743                           ff_database_items d,
4744                           ff_route_parameters rp,
4745                           ff_route_parameter_values rpv
4746                    where  u.user_entity_name = global_name || '_GLOBAL_UE'
4747                      and  u.user_entity_id = rpv.user_entity_id
4748                      and  d.user_entity_id = u.user_entity_id
4749                      and  rpv.route_parameter_id = rp.route_parameter_id
4750                      and  rpv.value = to_char(l_new_global_id));
4751 
4752 		ELSE
4753 
4754 		    -- Phase = 2
4755 
4756 
4757                     for r_global in c_global_ad(r_distinct.c_surrogate_key)
4758                     loop
4759                       delete ff_fdi_usages_f where formula_id = r_global.fid;
4760                       delete ff_compiled_info_f where formula_id = r_global.fid;
4761                     end loop;
4762 
4763                     -- Delete ff_route_parameter_values
4764                     -- associated with this global bug 3744555
4765                     -- and let them get recreated by the global triggers
4766                     delete ff_route_parameter_values
4767                     where  user_entity_id = (select user_entity_id
4768                       from ff_user_entities
4769                       where user_entity_name = r_distinct.c_true_key || '_GLOBAL_UE');
4770 
4771 		    delete from ff_globals_f
4772 		    where  global_id = r_distinct.c_surrogate_key;
4773 
4774 		    FOR each_row IN c_each_row(r_distinct.c_surrogate_key)
4775 		    LOOP
4776 
4777 		        r_each_row := each_row;
4778 
4779 
4780                         BEGIN
4781 		        insert into ff_globals_f
4782 		        (GLOBAL_ID
4783 		        ,EFFECTIVE_START_DATE
4784 		        ,EFFECTIVE_END_DATE
4785 		        ,BUSINESS_GROUP_ID
4786 		        ,LEGISLATION_CODE
4787 		        ,DATA_TYPE
4788 		        ,GLOBAL_NAME
4789 		        ,GLOBAL_DESCRIPTION
4790 		        ,GLOBAL_VALUE
4791 		        ,LAST_UPDATE_DATE
4792 		        ,LAST_UPDATED_BY
4793 		        ,LAST_UPDATE_LOGIN
4794 		        ,CREATED_BY
4795 		        ,CREATION_DATE)
4796 		        values
4797 		        (r_each_row.GLOBAL_ID
4798 		        ,r_each_row.EFFECTIVE_START_DATE
4799 		        ,r_each_row.EFFECTIVE_END_DATE
4800 		        ,r_each_row.BUSINESS_GROUP_ID
4801 		        ,r_each_row.LEGISLATION_CODE
4802 		        ,r_each_row.DATA_TYPE
4803 		        ,r_each_row.GLOBAL_NAME
4804 		        ,r_each_row.GLOBAL_DESCRIPTION
4805 		        ,r_each_row.GLOBAL_VALUE
4806 		        ,r_each_row.LAST_UPDATE_DATE
4810 		        ,r_each_row.CREATION_DATE);
4807 		        ,r_each_row.LAST_UPDATED_BY
4808 		        ,r_each_row.LAST_UPDATE_LOGIN
4809 		        ,r_each_row.CREATED_BY
4811 
4812                       EXCEPTION WHEN OTHERS THEN
4813                         hr_legislation.hrrunprc_trace_on;
4814                         hr_utility.trace('ins ff_globals_f');
4815                         hr_utility.trace('GLOBAL_NAME  ' ||
4816                           r_each_row.GLOBAL_NAME);
4820                           r_each_row.GLOBAL_VALUE);
4817                         hr_utility.trace('GLOBAL_ID  ' ||
4818                           to_char(r_each_row.GLOBAL_ID));
4819                         hr_utility.trace('GLOBAL_VALUE  ' ||
4821                         hr_utility.trace(':lc: ' || ':' ||
4822                           r_each_row.legislation_code || ':');
4823                         hr_legislation.hrrunprc_trace_off;
4824                         raise;
4825                       END;
4826 		    END LOOP each_row;
4827 
4828 		    remove(r_distinct.c_surrogate_key);
4829 
4830 		END IF;
4831 
4832 	    END IF;
4833 
4834 	EXCEPTION WHEN row_in_error THEN
4835 	    rollback to new_global_name;
4836 	END;
4837 
4838     END LOOP primary_keys;
4839 
4840 -- ena_cont_calc_trigger;
4841 
4842 END install_globals;
4843 
4844 --****************************************************************************
4845 -- INSTALLATION PROCEDURE FOR ALL FF DELIVERY
4846 --****************************************************************************
4847 
4848 PROCEDURE install (p_phase number)
4849 ----------------------------------
4850 IS
4851     -- Driver procedure to execute all formula installation procedures.
4852   core_selected NUMBER;
4853 
4854 BEGIN
4855 hr_legislation.hrrunprc_trace_on;
4856     hr_utility.trace('start ff_data_dict.install: ' || to_char(p_phase));
4857 hr_legislation.hrrunprc_trace_off;
4858 
4859     IF p_phase <> 1 and p_phase <>2 THEN
4860 	return;
4861     END IF;
4862 
4863     IF p_phase = 2 THEN
4864 
4865         select count(*)
4866         into   core_selected
4867         from   hr_legislation_installations
4868         where  legislation_code is null
4869         and    action in ('I', 'U', 'F');
4870 
4871     END IF;
4872 hr_legislation.hrrunprc_trace_on;
4873     hr_utility.trace('start install_ffc: ' || to_char(p_phase));
4874 hr_legislation.hrrunprc_trace_off;
4875 
4876     install_ffc(p_phase);  	--install ff_contexts
4877 hr_legislation.hrrunprc_trace_on;
4878     hr_utility.trace('start install_fft: ' || to_char(p_phase));
4879 hr_legislation.hrrunprc_trace_off;
4880 
4881     install_fft(p_phase);  	--install ff_Formula_types
4882 
4883 hr_legislation.hrrunprc_trace_on;
4884     hr_utility.trace('start install_formulas: ' || to_char(p_phase));
4885 hr_legislation.hrrunprc_trace_off;
4886 
4887     install_formulas(p_phase); 	--install formulas
4888 
4889 hr_legislation.hrrunprc_trace_on;
4890     hr_utility.trace('start install_routes: ' || to_char(p_phase));
4891 hr_legislation.hrrunprc_trace_off;
4892 
4893     install_routes(p_phase); 	--install routes,entities,db items
4894 
4895 hr_legislation.hrrunprc_trace_on;
4896     hr_utility.trace('start install_functions: ' || to_char(p_phase));
4897 hr_legislation.hrrunprc_trace_off;
4898 
4899     install_functions(p_phase); --install functions, context usages etc
4900 
4901 hr_legislation.hrrunprc_trace_on;
4902     hr_utility.trace('start install_qpreports: ' || to_char(p_phase));
4903 hr_legislation.hrrunprc_trace_off;
4904 
4905     install_qpreports(p_phase); --install quickpaint reports
4906 
4907 hr_legislation.hrrunprc_trace_on;
4908     hr_utility.trace('start install_globals: ' || to_char(p_phase));
4909 hr_legislation.hrrunprc_trace_off;
4910 
4911     install_globals(p_phase); 	--install globals
4912 
4913 hr_legislation.hrrunprc_trace_on;
4914     hr_utility.trace('exit ff_data_dict.install: ' || to_char(p_phase));
4915 hr_legislation.hrrunprc_trace_off;
4916 
4917 END install;
4918 
4919 END ff_data_dict;