DBA Data[Home] [Help]

PACKAGE BODY: APPS.HRI_BPL_SETUP_DIAGNOSTIC

Source


1 PACKAGE BODY hri_bpl_setup_diagnostic AS
2 /* $Header: hribdgsp.pkb 120.9 2006/12/11 09:55:24 msinghai noship $ */
3 
4 -- =========================================================================
5 --
6 -- OVERVIEW
7 -- --------
8 -- This package contains procedures to test the set up of DBI on the system.
9 -- Checks is performed for the following:
10 --  (a) Profiles
11 --  (b) Fast Formulas
12 --  (c) Triggers
13 --  (d) Key DBI Tables
14 --  (e) Job Family and Job Function
15 --  (f) Geography
16 --
17 -- DOCUMENT REFERENCE
18 -- ------------------
19 -- http://files.oraclecorp.com/content/AllPublic/SharedFolders/HRMS%20
20 -- Intelligence%20%28HRMSi%29%20-%20Documents-Public/Design%20Specifications
21 -- /hri_lld_dgn_system_stup.doc
22 --
23 -- =========================================================================
24 
25 
26   TYPE g_prd_type IS RECORD(
27      dbi_ind   NUMBER(10),
28      obiee_ind NUMBER(10),
29      all_ind   NUMBER(10));
30 
31   TYPE g_prd_type_tab IS TABLE OF g_prd_type INDEX BY VARCHAR2(100);
32 
33   g_prd_type_tab_v  g_prd_type_tab;
34 
35   g_object_name VARCHAR2(100);
36 
37   TYPE g_flex_structure_rec_type IS RECORD
38    (structure_name           VARCHAR2(240),
39     job_family_defined_msg   VARCHAR2(240),
40     job_function_defined_msg VARCHAR2(240));
41 
42   TYPE g_flex_structure_tab_type IS TABLE OF g_flex_structure_rec_type
43                                     INDEX BY VARCHAR2(80);
44 
45   g_debugging                BOOLEAN;
46   g_setup_rec                NUMBER;
47   g_global_start_date        DATE;
48   g_functional_area          VARCHAR2(30);
49 
50   -- Cursor to fetch records from the Diagnostics Table
51   CURSOR c_objects
52    (v_object_name      VARCHAR2,
53     v_object_type      VARCHAR2,
54     v_functional_area  VARCHAR2) IS
55   SELECT
56    stp.*
57   FROM
58    hri_adm_dgnstc_setup   stp
59   ,hri_adm_dgnstc_sbscrb  sbs
60   WHERE stp.object_type= v_object_type
61   AND stp.object_name = sbs.object_name
62   AND stp.object_type = sbs.object_type
63   AND sbs.functional_area_cd = v_functional_area
64   AND (v_object_name IS NULL
65     OR stp.object_name = v_object_name)
66   AND stp.enabled_flag = 'Y'
67   AND ((stp.foundation_hr_flag = 'Y' AND
68         hri_bpl_system.is_full_hr_installed = 'N')
69     OR hri_bpl_system.is_full_hr_installed = 'Y')
70   UNION ALL
71   SELECT
72    stp.*
73   FROM
74    hri_adm_dgnstc_setup  stp
75   WHERE stp.object_type= v_object_type
76   AND v_functional_area = 'ALL'
77   AND (v_object_name IS NULL
78     OR stp.object_name = v_object_name)
79   AND stp.enabled_flag = 'Y'
80   AND ((stp.foundation_hr_flag = 'Y' AND
81         hri_bpl_system.is_full_hr_installed = 'N')
82     OR hri_bpl_system.is_full_hr_installed = 'Y')
83   ORDER BY 1;
84 
85 -- ----------------------------------------------------------------------------
86 -- Switches debugging messages on or off. Setting to on will
87 -- mean extra debugging information will be generated when the
88 -- process is run.
89 -- ----------------------------------------------------------------------------
90 PROCEDURE set_debugging(p_on IN BOOLEAN) IS
91 
92 BEGIN
93 
94   g_debugging := p_on;
95 
96 END set_debugging;
97 
98 -- ----------------------------------------------------------------------------
99 -- Procedure msg logs a message
100 -- ----------------------------------------------------------------------------
101 PROCEDURE output(p_text IN VARCHAR2) IS
102 
103 BEGIN
104 
105   hri_bpl_conc_log.output(p_text);
106 
107 END output;
108 
109 -- ----------------------------------------------------------------------------
110 -- Procedure dbg decides whether to log the passed in message
111 -- depending on whether debug mode is set.
112 -- ----------------------------------------------------------------------------
113 PROCEDURE dbg(p_text IN VARCHAR2) IS
114 
115 BEGIN
116 
117   IF g_debugging THEN
118     output(p_text);
119   END IF;
120 
121 END dbg;
122 
123 -- ----------------------------------------------------------------------------
124 -- PROCEDURE trim_msg removes blank spaces and enter characters from the string
125 -- ----------------------------------------------------------------------------
126 FUNCTION trim_msg(p_text IN VARCHAR2)
127       RETURN VARCHAR2 IS
128 
129   l_text VARCHAR2(20000);
130 
131 BEGIN
132 
133   -- Remove blank spaces
134   l_text := TRIM(both ' ' FROM p_text);
135 
136   -- Remove Enter characters
137   l_text := TRIM(both fnd_global.local_chr(10) FROM l_text);
138 
139   RETURN l_text;
140 
141 END trim_msg;
142 
143 -- ----------------------------------------------------------------------------
144 -- Function GET_MESSAGE takes the message name and returns back the
145 -- message text
146 -- ----------------------------------------------------------------------------
147 FUNCTION get_message(p_message IN VARCHAR2)
148       RETURN VARCHAR2 IS
149 
150 BEGIN
151   --
152   fnd_message.set_name('HRI', p_message);
153   IF is_token_exist(p_message,'PRODUCT_NAME')
154   THEN
155     fnd_message.set_token('PRODUCT_NAME'
156                           ,get_product_name(g_object_name));
157   END IF;
158 
159   RETURN trim_msg(fnd_message.get);
160   --
161 END get_message;
162 
163 -------------------------------------------------------------------------------
164 --
165 -------------------------------------------------------------------------------
166 FUNCTION is_token_exist(p_message    IN   VARCHAR2,
167                         p_token_name IN   VARCHAR2)
168       RETURN BOOLEAN IS
169 --
170 l_exists BOOLEAN := FALSE;
171 --
172 BEGIN
173   --
174   IF instr(fnd_message.get_string('HRI',p_message),p_token_name,1) > 0 THEN
175     --
176     l_exists := TRUE ;
177     --
178   END IF;
179   --
180   RETURN l_exists;
181   --
182 END is_token_exist;
183 
184 -------------------------------------------------------------------------------
185 -- Get the product name being called by the Concurrect program.
186 -------------------------------------------------------------------------------
187 
188 FUNCTION get_product_name(p_object_name IN VARCHAR2)
189       RETURN VARCHAR2 IS
190 
191   l_product_name varchar2(1000);
192 
193 BEGIN
194    dbg('Entering get_product_name');
195 
196     IF     ((g_prd_type_tab_v(p_object_name).dbi_ind = 1
197        AND g_prd_type_tab_v(p_object_name).obiee_ind = 0
198        AND g_prd_type_tab_v(p_object_name).all_ind = 0)
199        OR ( p_object_name = 'HRI_IMPL_DBI')) THEN
200       --
201       l_product_name :=fnd_message.GET_STRING('HRI', 'HRI_407494_HRI_PRODUCT_NAME');
202       --
203     ELSIF  ((g_prd_type_tab_v(p_object_name).dbi_ind = 0
204        AND g_prd_type_tab_v(p_object_name).obiee_ind = 1
205        AND g_prd_type_tab_v(p_object_name).all_ind = 0)
206        OR  (p_object_name = 'HRI_IMPL_OBIEE')) THEN
207       --
208         l_product_name :=fnd_message.GET_STRING('HRI', 'HRI_407493_OBIEE_PRODUCT_NAME');
209       --
210     ELSIF  g_prd_type_tab_v(p_object_name).all_ind = 1 then
211 
212       l_product_name :=fnd_message.GET_STRING('HRI', 'HRI_407493_OBIEE_PRODUCT_NAME')||' & '||
213                              fnd_message.GET_STRING('HRI', 'HRI_407494_HRI_PRODUCT_NAME');
214     ELSE
215       l_product_name :=fnd_message.GET_STRING('HRI', 'HRI_407493_OBIEE_PRODUCT_NAME')||'/'||
216                              fnd_message.GET_STRING('HRI', 'HRI_407494_HRI_PRODUCT_NAME');
217     END IF;
218 
219    dbg('Exiting get_product_name');
220    RETURN l_product_name;
221 
222 END get_product_name;
223 
224 -- ----------------------------------------------------------------------------
225 -- Function get_profile_message takes the message name and returns back the
226 -- message text for a profile
227 -- ----------------------------------------------------------------------------
228 FUNCTION get_profile_message(p_message           IN   VARCHAR2,
229                              p_user_profile_name IN   VARCHAR2)
230       RETURN VARCHAR2 IS
231 
232 l_product_name VARCHAR2(1000);
233 BEGIN
234 
235   fnd_message.set_name('HRI', p_message);
236   fnd_message.set_token('PROFILE_NAME',p_user_profile_name);
237 
238   IF is_token_exist(p_message,'PRODUCT_NAME') THEN
239     l_product_name:= get_product_name(p_object_name => g_object_name);
240     fnd_message.set_token('PRODUCT_NAME',l_product_name);
241   END IF;
242 
243   RETURN trim_msg(fnd_message.get);
244 
245 END get_profile_message;
246 
247 
248 -- ----------------------------------------------------------------------------
249 -- Function get_ff_message takes the message name and returns back the
250 -- message text for a fast formula
251 -- ----------------------------------------------------------------------------
252 FUNCTION get_ff_message(p_message IN VARCHAR2,
253                         p_ff_name IN VARCHAR2)
254       RETURN VARCHAR2 IS
255 
256 BEGIN
257 
258   fnd_message.set_name('HRI', p_message);
259 
260   -- Set the Fast Formula name
261   fnd_message.set_token('FF_NAME',p_ff_name);
262 
263   IF is_token_exist(p_message,'PRODUCT_NAME')
264   THEN
265     fnd_message.set_token('PRODUCT_NAME',get_product_name(p_object_name => g_object_name));
266   END IF;
267 
268 
269   RETURN trim_msg(fnd_message.get);
270 
271 END get_ff_message;
272 
273 -- ----------------------------------------------------------------------------
274 -- Function is_dbi_date_format_correct checks the string format of DBI Global
275 -- Start Date. If the format is correct, then the global variable for DBI
276 -- Global Start Date is set to the date given in the string otherwise it is
277 -- set to sysdate
278 -- ----------------------------------------------------------------------------
279 FUNCTION is_dbi_date_format_correct(p_date_value IN VARCHAR2)
280       RETURN VARCHAR2 IS
281 
282 BEGIN
283 
284   -- If the value is null return wrong format
285   IF p_date_value IS NULL THEN
286     RETURN 'N';
287   END IF;
288 
289   -- Set the global start date
290   g_global_start_date := TRUNC(TO_DATE(p_date_value,'MM/DD/YYYY'));
291 
292   RETURN 'Y';
293 
294 EXCEPTION WHEN OTHERS THEN
295 
296   RETURN 'N';
297 
298 END is_dbi_date_format_correct;
299 
300 -- ----------------------------------------------------------------------------
301 -- FUNCTION get_user_profile_name is used to fetch the user profile name of a
302 -- profile.
303 -- ----------------------------------------------------------------------------
304 FUNCTION get_user_profile_name(p_profile_name IN VARCHAR2)
305       RETURN VARCHAR2 IS
306 
307   -- Cursor to fetch the user name of the profile
308   CURSOR c_user_profile_name IS
309   SELECT user_profile_option_name
310   FROM   fnd_profile_options_vl
311   WHERE  profile_option_name = p_profile_name;
312 
313   l_user_profile_name   VARCHAR2(1000);
314 
315 BEGIN
316 
317   OPEN  c_user_profile_name;
318   FETCH c_user_profile_name INTO l_user_profile_name;
319   CLOSE c_user_profile_name;
320 
321   RETURN l_user_profile_name;
322 
323 END get_user_profile_name;
324 
325 -- ----------------------------------------------------------------------------
326 -- Procedure check_profiles checks the values for the profiles defined in the
327 -- set up diagnostics table.
328 -- ----------------------------------------------------------------------------
329 PROCEDURE check_profile_option
330        (p_profile_name       IN VARCHAR2,
331         p_functional_area    IN VARCHAR2,
332         p_user_profile_name  OUT NOCOPY VARCHAR2,
333         p_profile_value      OUT NOCOPY VARCHAR2,
334         p_impact             OUT NOCOPY BOOLEAN,
335         p_impact_msg         OUT NOCOPY VARCHAR2,
336         p_doc_links_url      OUT NOCOPY VARCHAR2) IS
337 
338   l_value_code    VARCHAR2(240);
339   l_dynamic_sql   VARCHAR2(32000);
340 
341 BEGIN
342   g_functional_area:= p_functional_area;
343   -- Loop through all the profiles in the set up table
344   FOR l_profile IN c_objects(p_profile_name, 'PROFILE', p_functional_area) LOOP
345 
346     -- Get the user name of the profile
347     p_user_profile_name := get_user_profile_name(l_profile.object_name);
348     g_object_name := l_profile.object_name ;
349 
350     -- Get the profile option value
351     l_value_code := fnd_profile.value(l_profile.object_name);
352 
353     -- If the profile value is the exception value stored in the set up table,
354     -- store the impact message for this
355     IF (l_value_code = l_profile.exception_value) THEN
356 
357       -- Set impact flag
358       p_impact := TRUE;
359 
360       -- Store the specific impact message
361       p_impact_msg := get_profile_message
362                        (p_message => l_profile.impact_msg_name,
363                         p_user_profile_name => p_user_profile_name);
364 
365       -- Add the URL if provided
366       IF (l_profile.add_info_url IS NOT NULL) THEN
367         p_doc_links_url := l_profile.add_info_url;
368       END IF;
369 
370     -- Store the null impact message if
371     --   The value for the profile is not set
372     --   It is the DBI Global Start Date profile and
373     --   the profile value is in an incorrect format
374     ELSIF (l_value_code IS NULL OR
375            (l_profile.object_name = 'BIS_GLOBAL_START_DATE' AND
376             is_dbi_date_format_correct(l_value_code) = 'N')) THEN
377 
378       -- Set impact flag
379       p_impact := TRUE;
380 
381       -- Store the specific impact message
382       p_impact_msg := get_profile_message
383                        (p_message => l_profile.null_impact_msg_name,
384                         p_user_profile_name => p_user_profile_name);
385 
386       -- Add the URL if provided
387       IF (l_profile.add_info_url IS NOT NULL) THEN
388         p_doc_links_url := l_profile.add_info_url;
389       END IF;
390 
391     END IF;
392 
393     -- If the dynamic SQL is available for finding the profile value then use it else
394     -- use the existing profile value
395     l_dynamic_sql := hri_bpl_data_setup_dgnstc.get_dynamic_sql
396                       (p_dyn_sql_type => l_profile.dynamic_sql_type,
397                        p_dyn_sql      => l_profile.dynamic_sql);
398 
399     -- Run the SQL if given
400     IF l_dynamic_sql IS NOT NULL AND l_value_code IS NOT NULL THEN
401       EXECUTE IMMEDIATE l_dynamic_sql INTO p_profile_value USING l_value_code;
402     ELSE
403       p_profile_value := l_value_code;
404     END IF;
405 
406   END LOOP;
407 
408 EXCEPTION WHEN OTHERS THEN
409 
410   output('Exception Raised in check_profiles');
411   RAISE;
412 
413 END check_profile_option;
414 
415 -- ----------------------------------------------------------------------------
416 -- Procedure check_fast_formula checks the status of all the fast formulas
417 -- in the set up diagnostics table.
418 -- ----------------------------------------------------------------------------
419 PROCEDURE check_fast_formula
420        (p_ff_name          IN VARCHAR2,
421         p_functional_area  IN VARCHAR2,
422         p_type             IN VARCHAR2,
423         p_formula_tab      OUT NOCOPY fast_formula_tab_type,
424         p_impact_msg_tab   OUT NOCOPY impact_msg_tab_type) IS
425 
426   l_formula_tab          fast_formula_tab_type;
427   l_impact_msg_tab       impact_msg_tab_type;
428   l_status               VARCHAR2(240);
429   l_bg_index             PLS_INTEGER;
430   l_bg_name              VARCHAR2(100);
431   l_bg_id                NUMBER;
432   l_bg_without_ff        BOOLEAN;
433   l_ff_name   VARCHAR2(100);
434   l_dynamic_sql   VARCHAR2(32000);
435 
436   -- Reference type cursor is used when the Dynamic SQL fetches more than one records
437   TYPE ref_cursor_type   IS REF CURSOR;
438   c_user_defn_records    ref_cursor_type;
439 
440   -- Cursor to check the existence of the seeded fast formulas as on sysdate
441   CURSOR c_seeded_ff_nm(p_obj_nm VARCHAR2) IS
442     SELECT 'FFP'||formula_id||'_'||TO_CHAR(effective_start_date,'DDMMYYYY') ff_name
443     FROM   ff_formulas_f ff
444     WHERE  ff.formula_name = p_obj_nm
445     AND    ff.business_group_id IS NULL
446     AND    trunc(SYSDATE) BETWEEN ff.effective_start_date AND ff.effective_end_date
447     ORDER BY ff_name;
448 
449   -- Cursor to find the status of the fast formula
450   CURSOR c_status(p_ff_nm VARCHAR2) IS
451     SELECT CASE WHEN COUNT(DISTINCT status)=1 THEN
452              'Valid'
453            ELSE
454              'Invalid'
455            END status
456     FROM user_objects
457     WHERE object_name = p_ff_nm
458     AND   object_type IN ('PACKAGE','PACKAGE BODY');
459 
460 BEGIN
461 
462   dbg('Checking ff');
463 
464   -- Initialize variables
465   l_bg_index     := 0;
466 
467   -- Only process one type - SEEDED or USER
468   IF (p_type = 'SEEDED') THEN
469 
470     -- Loop through the seeded fast formulas in the diagnostics table
471     FOR l_ff IN c_objects(p_ff_name,'SEEDED_FAST_FORMULA',p_functional_area) LOOP
472       g_object_name := l_ff.object_name ;
473 
474       -- Find the current existing formulas
475       FOR l_seeded_ff_nm IN c_seeded_ff_nm(l_ff.object_name) LOOP
476 
477         -- Increment the counter
478         l_bg_index := l_bg_index + 1;
479 
480         -- Check the status of each formula
481         OPEN  c_status(l_seeded_ff_nm.ff_name);
482         FETCH c_status INTO l_status;
483         CLOSE c_status;
484 
485         -- Check if the fast formula is compiled
486         IF l_status = 'Invalid' THEN
487 
488           -- Fetch the exception status message
489           l_formula_tab(l_bg_index).status :=
490                     get_message(l_ff.exception_status_msg_cd);
491 
492           -- Fetch the impact message
493           l_formula_tab(l_bg_index).impact_msg :=
494                     get_ff_message('HRI_407170_FF_UCMP_IMPCT',l_ff.object_name);
495         ELSE
496 
497           -- Store the valid status message
498           l_formula_tab(l_bg_index).status :=
499                     get_message(l_ff.valid_status_msg_cd);
500         END IF;
501 
502       END LOOP;
503 
504     END LOOP;
505 
506   -- USER formula
507   ELSE
508 
509     -- Loop through the user defined fast formulas in the diagnostics table
510     FOR l_ff IN c_objects(p_ff_name,'USER_DEFN_FAST_FORMULA',p_functional_area) LOOP
511       g_object_name := l_ff.object_name ;
512 
513       -- Fetch the information for all business groups for this formula
514       l_dynamic_sql := hri_bpl_data_setup_dgnstc.get_dynamic_sql
515                         (p_dyn_sql_type => l_ff.dynamic_sql_type,
516                          p_dyn_sql      => l_ff.dynamic_sql);
517 
518       -- Execute dynamic sql
519       OPEN  c_user_defn_records
520       FOR   l_dynamic_sql
521       USING l_ff.object_name;
522 
523       -- Loop through all the business groups
524       LOOP
525 
526       -- Fetch a record
527       FETCH c_user_defn_records
528       INTO  l_bg_name, l_bg_id, l_ff_name;
529 
530       -- Exit when no further records found
531       EXIT WHEN (c_user_defn_records%NOTFOUND OR
532                  c_user_defn_records%NOTFOUND IS NULL);
533 
534       -- Increment the business group count
535       l_bg_index := l_bg_index + 1;
536 
537       -- Add record for the business group
538       l_formula_tab(l_bg_index).business_group_name := l_bg_name;
539 
540       -- If the formula is not defined for the business group
541       IF l_ff_name = 'FFP_' THEN
542 
543         l_formula_tab(l_bg_index).status :=
544                  get_message(l_ff.null_impact_msg_name);
545         l_bg_without_ff := true;
546 
547       -- Formula is defined for the business group
548       ELSE
549 
550         -- Fetch the status of the user defined fast formula
551         OPEN  c_status(l_ff_name);
552         FETCH c_status INTO l_status;
553         CLOSE c_status;
554 
555         -- Check if the fast formula is compiled
556         IF l_status = 'Invalid' THEN
557 
558           -- This fast formula has an invalid status
559           l_formula_tab(l_bg_index).status :=
560                       get_message(l_ff.exception_status_msg_cd);
561 
562           l_formula_tab(l_bg_index).impact_msg :=
563                       get_ff_message('HRI_407170_FF_UCMP_IMPCT',
564                                      l_ff.object_name);
565 
566         ELSIF l_status = 'Valid' THEN
567 
568           -- This fast formula has an invalid status
569           l_formula_tab(l_bg_index).status :=
570                       get_message(l_ff.valid_status_msg_cd);
571 
572           -- If the formula is not defined in Setup Business Group and should be
573           -- record this information
574           IF (l_bg_id <> 0 AND
575               (l_ff.object_name = 'HR_MOVE_TYPE' OR
576                l_ff.object_name = 'NORMALIZE_REVIEW_RATING' OR
577                l_ff.object_name = 'CATEGORIZE_PERSON_TYPE')) THEN
578 
579             -- This bit needs "genericising"
580             IF (l_ff.object_name = 'HR_MOVE_TYPE') THEN
581 
582               l_impact_msg_tab('HRI_407168_USR_LVRSN_IMPCT').impact_msg :=
583                       get_message('HRI_407168_USR_LVRSN_IMPCT');
584 
585             ELSIF (l_ff.object_name = 'NORMALIZE_REVIEW_RATING') THEN
586 
587               l_impact_msg_tab('HRI_407267_REVRTG_WRNGBG_IMPCT').impact_msg :=
588                       get_message('HRI_407267_REVRTG_WRNGBG_IMPCT');
589 
590             ELSIF (l_ff.object_name = 'CATEGORIZE_PERSON_TYPE') THEN
591 
592               l_impact_msg_tab('HRI_407284_CTRPRN_WRNGBG_IMPCT').impact_msg :=
593                       get_message('HRI_407284_CTRPRN_WRNGBG_IMPCT');
594             END IF;
595 
596           END IF;
597 
598         END IF; -- Compile Status
599 
600       END IF; -- Formula exists for BG
601 
602       END LOOP; -- BG Loop
603 
604       -- If a business group is found without a formula then
605       IF l_bg_without_ff THEN
606 
607         -- Store impact message
608         l_impact_msg_tab('HRI_407269_APPRTG_UNDEF_IMPCT').impact_msg :=
609                          get_message('HRI_407269_APPRTG_UNDEF_IMPCT');
610 
611       -- If the number of BG are 0 then store a message
612       ELSIF (l_bg_index = 0 AND
613              l_ff.object_name <> 'NORMALIZE_APPRAISAL_RATING' AND
614              l_ff.impact_msg_name IS NOT NULL) THEN
615 
616         l_impact_msg_tab(l_ff.impact_msg_name).impact_msg :=
617                 get_message(l_ff.impact_msg_name);
618         l_impact_msg_tab(l_ff.impact_msg_name).doc_links_url :=
619                 l_ff.add_info_url;
620 
621       END IF;
622 
623     END LOOP;
624 
625   END IF;
626 
627   -- Assign tables to output
628   p_formula_tab    := l_formula_tab;
629   p_impact_msg_tab := l_impact_msg_tab;
630 
631 EXCEPTION WHEN OTHERS THEN
632 
633   output('Exception Raised in check_fast_formula');
634   RAISE;
635 
636 END check_fast_formula;
637 
638 -- ----------------------------------------------------------------------------
639 -- PROCEDURE check_triggers checks whether the triggers are generated and
640 -- enabled
641 -- ----------------------------------------------------------------------------
642 PROCEDURE check_triggers(p_trigger_name      IN VARCHAR2,
643                          p_functional_area   IN VARCHAR2,
644                          p_generated         OUT NOCOPY VARCHAR2,
645                          p_enabled           OUT NOCOPY VARCHAR2,
646                          p_status            OUT NOCOPY VARCHAR2,
647                          p_impact            OUT NOCOPY BOOLEAN,
648                          p_impact_msg        OUT NOCOPY VARCHAR2,
649                          p_doc_links_url     OUT NOCOPY VARCHAR2) IS
650 
651   -- Cursor to check if the trigger is enabled and generated
652   CURSOR c_check_trigger(p_trigger_nm VARCHAR2) IS
653     SELECT generated_flag generated,
654            enabled_flag   enabled
655     FROM   pay_trigger_events
656     WHERE  short_name = p_trigger_nm;
657 
658   l_generated     VARCHAR2(5);
659   l_enabled       VARCHAR2(5);
660 
661 BEGIN
662 
663   dbg('Checking trigger');
664 
665   -- Loop through all the triggers in the set up table
666   FOR l_trigger IN c_objects(p_trigger_name,'TRIGGER',p_functional_area) LOOP
667     g_object_name := l_trigger.object_name;
668 
669     -- Fetch the values for the generated and enabled flag
670     OPEN c_check_trigger(l_trigger.object_name);
671     FETCH c_check_trigger INTO l_generated, l_enabled;
672     CLOSE c_check_trigger;
673 
674     -- Set the messages
675     IF (l_generated = 'Y' AND l_enabled = 'Y') THEN
676 
677       -- If the trigger is generated and enabled then there is no problem
678       p_status := get_message(l_trigger.valid_status_msg_cd);
679       p_impact := FALSE;
680 
681     ELSE
682 
683       -- Otherwise exception message has to be shown
684       p_status := get_message(l_trigger.exception_status_msg_cd);
685       p_impact := TRUE;
686 
687       -- To show impact message since a trigger is not enabled or not generated.
688       p_impact_msg := get_message('HRI_407171_TRGGR_IMPCT');
689       p_doc_links_url := get_message('HRI_407182_TRGGR_LINK');
690 
691     END IF;
692 
693     -- Find the lookup value for generated and enabled
694     p_generated := hr_bis.bis_decode_lookup('YES_NO',l_generated);
695     p_enabled   := hr_bis.bis_decode_lookup('YES_NO',l_enabled);
696 
697   END LOOP;
698 
699 EXCEPTION WHEN OTHERS THEN
700 
701   output('Exception Raised in check_triggers');
702   RAISE;
703 
704 END check_triggers;
705 
706 -- ----------------------------------------------------------------------------
707 -- PROCEDURE check_dbi_tables to check if the key DBI tables are populated
708 -- ----------------------------------------------------------------------------
709 PROCEDURE check_dbi_tables(p_table_name       IN VARCHAR2,
710                            p_functional_area  IN VARCHAR2,
711                            p_status           OUT NOCOPY VARCHAR2,
712                            p_impact           OUT NOCOPY BOOLEAN,
713                            p_impact_msg       OUT NOCOPY VARCHAR2,
714                            p_doc_links_url    OUT NOCOPY VARCHAR2) IS
715 
716   l_records            NUMBER;
717   l_stmt               VARCHAR2(100);
718 
719 BEGIN
720 
721   dbg('Checking tables');
722 
723   -- Get the table information
724   FOR l_tables IN c_objects(p_table_name,'TABLE',p_functional_area) LOOP
725     g_object_name := l_tables.object_name;
726 
727     -- Check whether data is present in the table
728     l_stmt := 'SELECT COUNT(*) FROM ' || UPPER(l_tables.object_name) ||
729               ' WHERE ROWNUM = 1';
730     EXECUTE IMMEDIATE l_stmt INTO l_records;
731 
732     -- If there is no data in the table
733     IF (l_records = 0) THEN
734 
735       -- Store the exception staus since the table is empty
736       p_impact := TRUE;
737       p_status := get_message(l_tables.exception_status_msg_cd);
738       p_impact_msg := get_message('HRI_407184_TABLE_IMPCT');
739       p_doc_links_url := get_message('HRI_407182_TRGGR_LINK');
740 
741     -- Table is populated
742     ELSE
743 
744       -- No impact
745       p_impact := FALSE;
746       p_status := get_message(l_tables.valid_status_msg_cd);
747 
748     END IF;
749 
750   END LOOP;
751 
752 EXCEPTION WHEN OTHERS THEN
753 
754   output('Exception Raised in check_dbi_tables');
755   RAISE;
756 
757 END check_dbi_tables;
758 
759 -- ------------------------------------
760 -- Checks details for a given job group
761 -- ------------------------------------
762 PROCEDURE check_job_group
763   (p_value_set_id       IN NUMBER,
764    p_job_type           IN VARCHAR2,
765    p_flex_structure_tab IN OUT NOCOPY job_flex_tab_type,
766    p_flex_type          OUT NOCOPY VARCHAR2) IS
767 
768   -- Cursor to find all the job keyflex structure codes that are
769   -- linked to a business group but do not have a segment linked
770   -- with the given value set
771   CURSOR check_keyflex_csr(v_valueset_id  NUMBER) IS
772   SELECT DISTINCT
773    flx.id_flex_num
774   ,flx.id_flex_structure_code
775   ,flx.id_flex_structure_name
776   FROM
777    hr_organization_information  hoi
778   ,fnd_id_flex_structures_vl    flx
779   WHERE hoi.org_information_context = 'Business Group Information'
780   AND flx.id_flex_num = hoi.org_information6
781   AND flx.id_flex_code= 'JOB'
782   AND flx.application_id = 800
783   AND NOT EXISTS
784     (SELECT /*+ NO_UNNEST */ null
785      FROM fnd_id_flex_segments_vl seg
786      WHERE seg.id_flex_code = 'JOB'
787      AND seg.application_id = 800
788      AND seg.id_flex_num = hoi.org_information6
789      AND seg.flex_value_set_id = v_valueset_id)
790   AND EXISTS
791     (SELECT /*+ NO_UNNEST */ null
792      FROM per_periods_of_service pps
793      WHERE pps.business_group_id = hoi.organization_id
794      AND NVL(pps.actual_termination_date, g_global_start_date) >= g_global_start_date);
795 
796   -- Cursor to find all non global job descriptive flexfield contexts that
797   -- do not have a segment linked with the given value set and do not have
798   -- a global segment available
799   CURSOR check_dscflex_csr(v_valueset_id  NUMBER) IS
800   SELECT
801    ctxt.descriptive_flex_context_code
802   ,ctxt.descriptive_flex_context_name
803   FROM
804    fnd_descr_flex_contexts_vl  ctxt
805   WHERE ctxt.descriptive_flexfield_name = 'PER_JOBS'
806   AND ctxt.application_id = 800
807   AND ctxt.enabled_flag = 'Y'
808   AND ctxt.global_flag = 'N'
809   AND NOT EXISTS
810    (SELECT NULL
811     FROM
812      fnd_descr_flex_col_usage_vl  col
813     WHERE ctxt.application_id = col.application_id
814     AND ctxt.descriptive_flexfield_name = col.descriptive_flexfield_name
815     AND ctxt.descriptive_flex_context_code = col.descriptive_flex_context_code
816     AND col.flex_value_set_id = v_valueset_id)
817   AND NOT EXISTS
818    (SELECT NULL
819     FROM
820      fnd_descr_flex_contexts_vl   ctxt2
821     ,fnd_descr_flex_col_usage_vl  col2
822     WHERE ctxt2.application_id = ctxt.application_id
823     AND ctxt2.descriptive_flexfield_name = ctxt.descriptive_flexfield_name
824     AND ctxt2.application_id = col2.application_id
825     AND ctxt2.descriptive_flexfield_name = col2.descriptive_flexfield_name
826     AND ctxt2.descriptive_flex_context_code = col2.descriptive_flex_context_code
827     AND ctxt2.global_flag = 'Y'
828     AND col2.flex_value_set_id = v_valueset_id);
829 
830   l_index     VARCHAR2(240);
831 
832 BEGIN
833 
834   -- Get the flexfield type
835   p_flex_type := hri_opl_jobh.get_flexfield_type
836                   (p_job_type     => p_job_type,
837                    p_value_set_id => p_value_set_id);
838 
839   -- Load structure table with the undefined structures from the relevant cursor
840   IF (p_flex_type = 'KEY') THEN
841 
842     FOR keyflex_rec IN check_keyflex_csr(p_value_set_id) LOOP
843  --     g_object_name := l_tables.object_name;
844 
845       l_index := p_flex_type || '|' || keyflex_rec.id_flex_structure_code;
846 
847       p_flex_structure_tab(l_index).structure_name :=
848               keyflex_rec.id_flex_structure_name;
849 
850       IF (p_job_type = 'JOB_FAMILY') THEN
851         p_flex_structure_tab(l_index).job_family_defined_msg :=
852                        get_message('HRI_407177_JOB_UNDEF_STTS');
853       ELSIF (p_job_type = 'JOB_FUNCTION') THEN
854         p_flex_structure_tab(l_index).job_function_defined_msg :=
855                        get_message('HRI_407177_JOB_UNDEF_STTS');
856       END IF;
857 
858     END LOOP;
859 
860   ELSIF (p_flex_type = 'DESCRIPTIVE') THEN
861 
862     FOR dscflex_rec IN check_dscflex_csr(p_value_set_id) LOOP
863 
864       l_index := p_flex_type || '|' || dscflex_rec.descriptive_flex_context_code;
865 
866       p_flex_structure_tab(l_index).structure_name :=
867               dscflex_rec.descriptive_flex_context_name;
868 
869       IF (p_job_type = 'JOB_FAMILY') THEN
870         p_flex_structure_tab(l_index).job_family_defined_msg :=
871                        get_message('HRI_407177_JOB_UNDEF_STTS');
872       ELSIF (p_job_type = 'JOB_FUNCTION') THEN
873         p_flex_structure_tab(l_index).job_function_defined_msg :=
874                        get_message('HRI_407177_JOB_UNDEF_STTS');
875       END IF;
876 
877     END LOOP;
878 
879   END IF;
880 
881 END check_job_group;
882 
883 -- ----------------------------------------------------------------------------
884 -- PROCEDURE check_job checks the set up for Job Family and Job Function.
885 -- ----------------------------------------------------------------------------
886 PROCEDURE check_job(p_job_family_mode        OUT NOCOPY VARCHAR2,
887                     p_job_function_mode      OUT NOCOPY VARCHAR2,
888                     p_flex_structure_tab     OUT NOCOPY job_flex_tab_type,
889                     p_impact                 OUT NOCOPY BOOLEAN,
890                     p_impact_msg             OUT NOCOPY VARCHAR2,
891                     p_doc_links_url          OUT NOCOPY VARCHAR2) IS
892 
893   l_family_vl            VARCHAR2(100);
894   l_function_vl          VARCHAR2(100);
895   l_job_family_impact    BOOLEAN;
896   l_job_function_impact  BOOLEAN;
897 
898 BEGIN
899 
900   -- Do not check job set up for foundation HR
901   IF hri_bpl_system.is_full_hr_installed = 'Y' THEN
902 
903     -- If the global start date, job family or job function profile is not set correctly
904     -- then store an impact message and return
905     IF (fnd_profile.value('HR_BIS_JOB_FAMILY')   IS NULL AND
906         fnd_profile.value('HR_BIS_JOB_FUNCTION') IS NULL) THEN
907 
908       -- Set the message up
909       fnd_message.set_name
910        ('HRI','HRI_407183_UNSET_JOB_PRF_IMPCT');
911 
912       -- Set the Profile names
913       fnd_message.set_token
914        ('PROFILE_NAME1',get_user_profile_name('BIS_GLOBAL_START_DATE'));
915       fnd_message.set_token
916        ('PROFILE_NAME2',get_user_profile_name('HR_BIS_JOB_FAMILY'));
917       fnd_message.set_token
918        ('PROFILE_NAME3',get_user_profile_name('HR_BIS_JOB_FUNCTION'));
919 
920       -- Store the general impact message
921       p_impact     := TRUE;
922       p_impact_msg := trim_msg(fnd_message.get);
923 
924     ELSE
925 
926       -- Find the profile value for Job Family and Job Function
927       l_family_vl   := fnd_profile.value('HR_BIS_JOB_FAMILY');
928       l_function_vl := fnd_profile.value('HR_BIS_JOB_FUNCTION');
929 
930       -- Get the setup information for job family
931       check_job_group(p_value_set_id       => l_family_vl,
932                       p_job_type           => 'JOB_FAMILY',
933                       p_flex_structure_tab => p_flex_structure_tab,
934                       p_flex_type          => p_job_family_mode);
935 
936       -- Get the setup information for job function
937       check_job_group(p_value_set_id       => l_function_vl,
938                       p_job_type           => 'JOB_FUNCTION',
939                       p_flex_structure_tab => p_flex_structure_tab,
940                       p_flex_type          => p_job_function_mode);
941 
942       -- If any structures are returned in the table then there may be impact
943       BEGIN
944         IF (p_flex_structure_tab.FIRST IS NOT NULL) THEN
945 
946           -- Store the general impact message
947           p_impact        := TRUE;
948           p_impact_msg    := get_message('HRI_407172_JOB_IMPCT');
949           p_doc_links_url := get_message('HRI_407181_JOB_LINK');
950 
951         ELSE
952 
953           -- No impact
954           p_impact := FALSE;
955 
956         END IF;
957 
958       -- Trap exceptions if the structure table is empty
959       EXCEPTION WHEN OTHERS THEN
960         null;
961       END;
962 
963     END IF; -- Profile setup correct
964 
965   END IF; -- Shared HR
966 
967 EXCEPTION WHEN OTHERS THEN
968 
969   output('Exception Raised in check_job');
970   RAISE;
971 
972 END check_job;
973 
974 -- ----------------------------------------------------------------------------
975 -- PROCEDURE check_geography checks if the set up for Region. It
976 -- checks all the structures in Additional Location Details for the Region
977 -- segment.
978 -- ----------------------------------------------------------------------------
979 PROCEDURE check_geography(p_context_name     OUT NOCOPY VARCHAR2,
980                           p_flex_column      OUT NOCOPY VARCHAR2,
981                           p_status           OUT NOCOPY VARCHAR2,
982                           p_impact           OUT NOCOPY BOOLEAN,
983                           p_impact_msg       OUT NOCOPY VARCHAR2) IS
984 
985   -- Cursor to find the attribute for Region
986   CURSOR c_reg_attr IS
987   SELECT bfm.application_column_name
988   FROM
989    bis_flex_mappings_v   bfm
990   ,bis_dimensions        bd
991   WHERE bfm.dimension_id = bd.dimension_id
992   AND bd.short_name = 'GEOGRAPHY'
993   AND bfm.level_short_name = 'REGION'
994   AND bfm.application_id = 800;
995 
996   -- Cursor which finds the structures in the descriptive flexfield
997   -- 'Additional Location Details' that have a segment that uses
998   -- an attribute defined for Region
999   CURSOR c_reg_structures(p_attribute VARCHAR2) IS
1000   SELECT
1001    cntxt.descriptive_flex_context_name
1002   FROM
1003    fnd_descr_flex_col_usage_vl  col
1004   ,fnd_descr_flex_contexts_vl   cntxt
1005   WHERE col.application_id = 800
1006   AND col.descriptive_flexfield_name = 'HR_LOCATIONS'
1007   AND application_column_name = p_attribute
1008   AND cntxt.descriptive_flexfield_name = col.descriptive_flexfield_name
1009   AND cntxt.descriptive_flex_context_code = col.descriptive_flex_context_code
1010   AND col.application_id = cntxt.application_id;
1011 
1012 BEGIN
1013 
1014   -- Do not check geography set up for foundation HR
1015   IF hri_bpl_system.is_full_hr_installed = 'Y' THEN
1016 
1017     -- Get the column the region flex field segment is mapped to
1018     OPEN  c_reg_attr;
1019     FETCH c_reg_attr INTO p_flex_column;
1020     CLOSE c_reg_attr;
1021 
1022     -- If the region segment attribute is not null then find the
1023     -- flexfield structures using the region atribute
1024     IF p_flex_column IS NOT NULL THEN
1025 
1026       -- Find whether the location flexfield has the region column
1027       OPEN c_reg_structures(p_flex_column);
1028       FETCH c_reg_structures INTO p_context_name;
1029       CLOSE c_reg_structures;
1030 
1031     END IF;
1032 
1033     -- If the location structure has no region attribute then set status
1034     -- to undefined
1035     IF (p_context_name IS NULL) THEN
1036 
1037       p_impact := TRUE;
1038       p_status := get_message('HRI_407179_GEO_UNDEF_STTS');
1039       p_impact_msg := get_message('HRI_407173_GEO_IMPCT');
1040 
1041      -- Otherwise the geography setup is fine
1042     ELSE
1043 
1044       p_impact := FALSE;
1045       p_status := get_message('HRI_407178_GEO_DEF_STTS');
1046 
1047     END IF;
1048 
1049   END IF;
1050 
1051 EXCEPTION WHEN OTHERS THEN
1052 
1053   output('Exception Raised in check_geography');
1054   RAISE;
1055 
1056 END check_geography;
1057 
1058 -- ----------------------------------------------------------------------------
1059 -- PROCEDURE check_buckets to check if the number of ranges in the HRI buckets
1060 -- are correct.
1061 -- ----------------------------------------------------------------------------
1062 PROCEDURE check_buckets(p_bucket_name       IN VARCHAR2,
1063                         p_functional_area   IN VARCHAR2,
1064                         p_user_bucket_name  OUT NOCOPY VARCHAR2,
1065                         p_status            OUT NOCOPY VARCHAR2,
1066                         p_impact            OUT NOCOPY BOOLEAN,
1067                         p_impact_msg        OUT NOCOPY VARCHAR2,
1068                         p_doc_links_url     OUT NOCOPY VARCHAR2) IS
1069 
1070   l_range              VARCHAR2(1);
1071   l_bucket_name        VARCHAR2(240);
1072   l_dynamic_sql        VARCHAR2(32000);
1073 
1074   CURSOR bucket_name_csr(v_bucket_name VARCHAR2) IS
1075   SELECT name
1076   FROM bis_bucket_vl
1077   WHERE short_name = v_bucket_name;
1078 
1079 BEGIN
1080 
1081   dbg('Checking buckets');
1082 
1083   -- Get the bucket metadata
1084   FOR l_buckets IN c_objects(p_bucket_name, 'BUCKET', p_functional_area) LOOP
1085 
1086     -- Execute the dynamic sql to get the ranges defined for the bucket
1087     l_dynamic_sql := hri_bpl_data_setup_dgnstc.get_dynamic_sql
1088                       (p_dyn_sql_type => l_buckets.dynamic_sql_type,
1089                        p_dyn_sql      => l_buckets.dynamic_sql);
1090     EXECUTE IMMEDIATE l_dynamic_sql
1091     INTO  l_range;
1092 
1093     -- If the bucket is invalid
1094     IF l_range = 'N' THEN
1095 
1096       -- Store the impact message that is to be displayed since the bucket
1097       -- does not have correct number of ranges
1098       p_impact := TRUE;
1099       p_impact_msg := get_message(l_buckets.impact_msg_name);
1100       p_doc_links_url := l_buckets.add_info_url;
1101       p_status := get_message(l_buckets.exception_status_msg_cd);
1102 
1103     ELSE
1104 
1105       -- No impact
1106       p_impact := FALSE;
1107       p_status := get_message(l_buckets.valid_status_msg_cd);
1108 
1109     END IF;
1110 
1111     -- Get the bucket name
1112     OPEN bucket_name_csr(l_buckets.object_name);
1113     FETCH bucket_name_csr INTO p_user_bucket_name;
1114     CLOSE bucket_name_csr;
1115 
1116     -- Use bucket code if the name is not found
1117     IF (p_user_bucket_name IS NULL) THEN
1118       p_user_bucket_name := p_bucket_name;
1119     END IF;
1120 
1121   END LOOP;
1122 
1123 EXCEPTION WHEN OTHERS THEN
1124 
1125   output('Exception Raised in check_buckets');
1126   RAISE;
1127 
1128 END check_buckets;
1129 
1130 -- ----------------------------------------------------------------------------
1131 -- PROCEDURE pplt_obj_farea_tab is populate PRODUCT NAME(DBI/OBIEE/ALL)
1132 -- flags for all the objects based on functional area.
1133 -- ----------------------------------------------------------------------------
1134 PROCEDURE pplt_obj_farea_tab IS
1135 
1136   l_obiee_flag VARCHAR2(10) := 'N';
1137   l_dbi_flag   VARCHAR2(10) := 'N';
1138   l_all_flag   VARCHAR2(10) := 'N';
1139 
1140   -- Cursor to load product name table
1141   CURSOR prd_name_csr IS
1142      SELECT sub.object_name, sub.functional_area_cd
1143      FROM hri_adm_dgnstc_sbscrb sub
1144      ORDER BY sub.object_name;
1145 
1146   l_object_name         VARCHAR2(100);
1147   l_functional_area_cd  VARCHAR2(100);
1148   l_object_name_prv     VARCHAR2(100);
1149 
1150 BEGIN
1151 
1152   OPEN prd_name_csr;
1153   LOOP
1154 
1155     FETCH prd_name_csr
1156     INTO l_object_name,l_functional_area_cd;
1157 
1158     EXIT WHEN prd_name_csr % NOTFOUND;
1159 
1160     IF NOT(g_prd_type_tab_v.EXISTS(l_object_name)) THEN
1161       --
1162       g_prd_type_tab_v(l_object_name).obiee_ind := 0;
1163       g_prd_type_tab_v(l_object_name).dbi_ind := 0;
1164       g_prd_type_tab_v(l_object_name).all_ind := 0;
1165       --
1166     END IF;
1167 
1168     IF(l_functional_area_cd LIKE 'OBIEE%') THEN
1169       --
1170       g_prd_type_tab_v(l_object_name).obiee_ind := 1;
1171       --
1172     END IF;
1173 
1174     IF(l_functional_area_cd IN('BENEFITS',  'WRKFC_BDGT_MNGMNT') OR(l_functional_area_cd LIKE 'PPL%')) THEN
1175        --
1176        g_prd_type_tab_v(l_object_name).dbi_ind := 1;
1177        --
1178     END IF;
1179 
1180     IF(g_prd_type_tab_v(l_object_name).obiee_ind = 1)
1181      AND(g_prd_type_tab_v(l_object_name).dbi_ind = 1) THEN
1182       --
1183       g_prd_type_tab_v(l_object_name).all_ind := 1;
1184       --
1185     END IF;
1186     --
1187   END LOOP;
1188   CLOSE prd_name_csr;
1189 END  pplt_obj_farea_tab;
1190 --
1191 --
1192 
1193 END hri_bpl_setup_diagnostic;