DBA Data[Home] [Help]

PACKAGE BODY: APPS.BSC_COLOR_CALC_UTIL

Source


1 PACKAGE BODY BSC_COLOR_CALC_UTIL AS
2 /* $Header: BSCCUTLB.pls 120.6.12000000.1 2007/07/17 07:43:38 appldev noship $ */
3 
4 
5 FUNCTION get_weighted_obj_color (
6   p_pbjective_id      IN NUMBER
7 , p_weighted_avg_val  IN NUMBER
8 )
9 RETURN NUMBER;
10 
11 PROCEDURE get_rollup_obj_color (
12   p_rollup_type IN bsc_kpis_b.color_rollup_type%TYPE
13 , p_colors      IN BSC_UPDATE_UTIL.t_array_of_number
14 , p_num_colors  IN NUMBER
15 , x_color       OUT NOCOPY NUMBER
16 , x_kpi_index   OUT NOCOPY NUMBER
17 );
18 
19 
20 /*
21  * Get_Kpi_Measure_Threshold: Returns the Threshold properties as table.
22  * First it checks threshold corresponding to KPI, in not defined then it
23  * picks the Objective threshold for the KPI (Measure) threshold for color calculation.
24  */
25 FUNCTION Get_Kpi_Measure_Threshold (
26   p_indicator       IN         NUMBER
27 , p_kpi_measure_id  IN         NUMBER
28 ) RETURN Threshold_Prop_Table IS
29 
30   l_color_range_id   NUMBER;
31   l_threshold_Table  Threshold_Prop_Table;
32   l_count            NUMBER;
33   l_config_type      NUMBER;
34 
35   -- For P & L Objective threshold.
36   CURSOR c_pl_color IS
37     SELECT color_range_id
38     FROM bsc_color_type_props
39     WHERE indicator  = p_indicator
40     --AND  kpi_measure_id = p_kpi_measure_id;
41     AND  property_value = 1;
42   -- For kpi_measure threshold.
43   CURSOR c_kpi_measure_color IS
44     SELECT color_range_id
45     FROM bsc_color_type_props
46     WHERE indicator  = p_indicator
47     AND  kpi_measure_id = p_kpi_measure_id;
48 
49   -- For weight Objective threshold.
50   CURSOR c_objective_color IS
51     SELECT color_range_id
52     FROM bsc_color_type_props
53     WHERE indicator = p_indicator
54     AND kpi_measure_id IS NULL;
55 
56   CURSOR c_threshold_values IS
57     SELECT high, color_id
58     FROM bsc_color_ranges
59     WHERE color_range_id = l_color_range_id
60     ORDER BY color_range_sequence;
61 
62 BEGIN
63   SELECT config_type
64   INTO   l_config_type
65   FROM   bsc_kpis_b
66   WHERE  indicator = p_indicator;
67   IF (l_config_type = 3 ) THEN
68     FOR c_pl_color_range IN c_pl_color LOOP
69       l_color_range_id := c_pl_color_range.color_range_id;
70     END LOOP;
71   ELSIF (p_kpi_measure_id IS NULL) THEN  -- Get Threshold for Weighted Objective.
72     FOR c_objective_range IN c_objective_color LOOP
73       l_color_range_id := c_objective_range.color_range_id;
74     END LOOP;
75   ELSE  -- Get Threshold for kpi_measure.
76     FOR c_kpi_measure_range IN c_kpi_measure_color LOOP
77       l_color_range_id := c_kpi_measure_range.color_range_id;
78     END LOOP;
79   END IF;
80 
81   l_count := 1;
82   FOR c_thresholds IN c_threshold_values LOOP
83     l_threshold_Table(l_count).THRESHOLD := c_thresholds.high;
84     l_threshold_Table(l_count).COLOR_ID  := c_thresholds.color_id;
85     l_count := l_count + 1;
86   END LOOP;
87 
88   RETURN l_threshold_Table;
89 EXCEPTION
90   WHEN OTHERS THEN
91     BSC_MESSAGE.Add(x_message => SQLERRM,
92                     x_source => 'BSC_COLOR_CALC_UTIL.Get_Kpi_Measure_Threshold');
93     RETURN l_threshold_Table;
94 END Get_Kpi_Measure_Threshold;
95 
96 
97 FUNCTION get_color_perf_seq (
98   p_color_id  IN  bsc_sys_colors_b.color_id%TYPE
99 )
100 RETURN NUMBER IS
101 
102   l_index         NUMBER;
103   l_array_colors  BSC_COLOR_REPOSITORY.t_array_colors;
104   l_color_rec     BSC_COLOR_REPOSITORY.t_color_rec;
105 
106 BEGIN
107 
108   l_array_colors := BSC_COLOR_REPOSITORY.get_color_props();
109 
110   FOR l_index IN 1 .. l_array_colors.COUNT LOOP
111     l_color_rec := l_array_colors(l_index);
112     IF l_color_rec.color_id = p_color_id THEN
113       RETURN l_color_rec.perf_seq;
114     END IF;
115   END LOOP;
116 
117   RETURN NULL;
118 
119 EXCEPTION
120   WHEN OTHERS THEN
121     BSC_MESSAGE.Add(x_message => SQLERRM,
122                     x_source => 'BSC_COLOR_CALC_UTIL.get_color_perf_seq');
123     RETURN NULL;
124 END get_color_perf_seq;
125 
126 
127 
128 FUNCTION get_objective_color_method (
129   p_pbjective_id IN NUMBER
130 )
131 RETURN NUMBER IS
132   CURSOR c_obj_color_prop IS
133     SELECT weighted_color_method
134       FROM bsc_kpis_b
135       WHERE indicator = p_pbjective_id;
136 
137   l_color_method  NUMBER;
138 
139 BEGIN
140   IF c_obj_color_prop%ISOPEN THEN
141     CLOSE c_obj_color_prop;
142   END IF;
143 
144   OPEN c_obj_color_prop;
145   FETCH c_obj_color_prop INTO l_color_method;
146   IF c_obj_color_prop%NOTFOUND THEN
147     RETURN NULL;
148   END IF;
149 
150   CLOSE c_obj_color_prop;
151 
152   RETURN l_color_method;
153 
154 EXCEPTION
155   WHEN OTHERS THEN
156     IF c_obj_color_prop%ISOPEN THEN
157       CLOSE c_obj_color_prop;
158     END IF;
159     BSC_MESSAGE.Add(x_message => SQLERRM,
160                     x_source => 'BSC_COLOR_CALC_UTIL.get_objective_color_method');
161     RETURN NULL;
162 END get_objective_color_method;
163 
164 
165 FUNCTION get_kpi_measure_weight (
166   p_objective_id    IN bsc_kpis_b.indicator%TYPE
167 , p_kpi_measure_id  IN bsc_kpi_measure_props.kpi_measure_id%TYPE
168 )
169 RETURN NUMBER IS
170   CURSOR c_kpi_measure_weight IS
171     SELECT weight
172       FROM bsc_kpi_measure_weights
173       WHERE kpi_measure_id = p_kpi_measure_id
174       AND   indicator = p_objective_id;
175   l_weight  NUMBER;
176 BEGIN
177   l_weight := 0;
178   IF c_kpi_measure_weight%ISOPEN THEN
179     CLOSE c_kpi_measure_weight;
180   END IF;
181 
182   OPEN c_kpi_measure_weight;
183   FETCH c_kpi_measure_weight INTO l_weight;
184   IF c_kpi_measure_weight%NOTFOUND THEN
185     RETURN 0;
186   END IF;
187 
188   CLOSE c_kpi_measure_weight;
189 
190   RETURN l_weight;
191 
192 EXCEPTION
193   WHEN OTHERS THEN
194     IF c_kpi_measure_weight%ISOPEN THEN
195       CLOSE c_kpi_measure_weight;
196     END IF;
197     BSC_MESSAGE.Add(x_message => SQLERRM,
198                     x_source => 'BSC_COLOR_CALC_UTIL.get_kpi_measure_weight');
199     RETURN 0;
200 END get_kpi_measure_weight;
201 
202 
203 FUNCTION get_color_numeric_equivalent (
204   p_color_id  IN NUMBER
205 )
206 RETURN NUMBER IS
207 
208   l_index         NUMBER;
209   l_array_colors  BSC_COLOR_REPOSITORY.t_array_colors;
210   l_color_rec     BSC_COLOR_REPOSITORY.t_color_rec;
211 
212 BEGIN
213 
214   l_array_colors := BSC_COLOR_REPOSITORY.get_color_props();
215   FOR l_index IN 1 .. l_array_colors.COUNT LOOP
216     l_color_rec := l_array_colors(l_index);
217     IF l_color_rec.color_id = p_color_id THEN
218       RETURN l_color_rec.numeric_eq;
219     END IF;
220   END LOOP;
221 
222   RETURN 0;
223 
224 EXCEPTION
225   WHEN OTHERS THEN
226     BSC_MESSAGE.Add(x_message => SQLERRM,
227                     x_source => 'BSC_COLOR_CALC_UTIL.get_color_numeric_equivalent');
228     RETURN 0;
229 END get_color_numeric_equivalent;
230 
231 
232 FUNCTION get_max_count (
233   p_array_of_number  IN BSC_UPDATE_UTIL.t_array_of_number
234 )
235 RETURN NUMBER IS
236   l_counter    NUMBER;
237   l_max_count  NUMBER;
238 BEGIN
239   l_max_count := 0;
240 
241   IF p_array_of_number IS NOT NULL AND p_array_of_number.COUNT > 0 THEN
242     l_counter := p_array_of_number.FIRST;
243     WHILE l_counter IS NOT NULL LOOP
244       IF l_max_count < p_array_of_number(l_counter) THEN
245         l_max_count := p_array_of_number(l_counter);
246       END IF;
247       l_counter := p_array_of_number.NEXT(l_counter);
248     END LOOP;
249   END IF;
250 
251   RETURN l_max_count;
252 EXCEPTION
253   WHEN OTHERS THEN
254     RETURN 0;
255 END get_max_count;
256 
257 
258 
259 PROCEDURE initialize_color_array (
260   p_array_of_number  IN OUT NOCOPY BSC_UPDATE_UTIL.t_array_of_number
261 )
262 IS
263   l_index         NUMBER;
264   l_array_colors  BSC_COLOR_REPOSITORY.t_array_colors;
265   l_color_rec     BSC_COLOR_REPOSITORY.t_color_rec;
266 
267 BEGIN
268 
269   l_array_colors := BSC_COLOR_REPOSITORY.get_color_props();
270   FOR l_index IN 1 .. l_array_colors.COUNT LOOP
271     l_color_rec := l_array_colors(l_index);
272     p_array_of_number(l_color_rec.color_id) := 0;
273   END LOOP;
274 
275 EXCEPTION
276   WHEN OTHERS THEN
277     NULL;
278 END initialize_color_array;
279 
280 
281 FUNCTION Calc_Obj_Color_By_Weights (
282   p_objective_color_rec  IN BSC_UPDATE_COLOR.t_objective_color_rec
283 )
284 RETURN BOOLEAN IS
285   CURSOR c_dim_comb(p_indicator NUMBER, p_tab_id NUMBER) IS
286     SELECT DISTINCT
287            dim_level1 || dim_level2 || dim_level3 || dim_level4 || dim_level5 || dim_level6 || dim_level7 || dim_level8 || period_id dim_comb,
288            dim_level1, dim_level2, dim_level3, dim_level4, dim_level5, dim_level6, dim_level7, dim_level8,
289            period_id
290       FROM bsc_sys_kpi_colors
291       WHERE indicator = p_indicator
292       AND   tab_id = p_tab_id;
293   l_dim_comb  c_dim_comb%ROWTYPE;
294 
295   CURSOR c_kpi_colors(p_indicator NUMBER, p_tab_id NUMBER, p_dim_comb VARCHAR2) IS
296     SELECT kpi_measure_id, kpi_color
297       FROM bsc_sys_kpi_colors
298       WHERE dim_level1 || dim_level2 || dim_level3 || dim_level4 || dim_level5 || dim_level6 || dim_level7 || dim_level8 ||  period_id = p_dim_comb
299       AND   indicator = p_indicator
300       AND   tab_id = p_tab_id
301     UNION -- bsc_sys_kpi_colors may not contain a color entry for 'color enabled' KPIs for which data has not been loaded
302     SELECT kpi_measure_id, BSC_COLOR_REPOSITORY.NO_COLOR kpi_color
303       FROM bsc_kpi_measure_props
304       WHERE indicator = p_indicator
305       AND   disable_color = 'F'
306       AND   kpi_measure_id NOT IN
307                            ( SELECT kpi_measure_id FROM bsc_sys_kpi_colors
308                              WHERE indicator = p_indicator
309                              AND   tab_id = p_tab_id
310                            );
311   l_kpi_colors  c_kpi_colors%ROWTYPE;
312 
313   l_obj_color               NUMBER;
314   l_kpi_weight              NUMBER;
315   l_num_eq                  NUMBER;
316   l_result                  NUMBER;
317   l_weighted_average_val    NUMBER;
318   l_set_no_color            BOOLEAN;
319   e_unexpected_error        EXCEPTION;
320 
321 BEGIN
322 
323   FOR l_dim_comb IN c_dim_comb(p_objective_color_rec.objective_id, p_objective_color_rec.tab_id) LOOP
324 
325     IF l_dim_comb.dim_comb IS NOT NULL THEN
326 
327       l_obj_color := BSC_COLOR_REPOSITORY.NO_COLOR;
328       l_set_no_color := FALSE;
329       l_weighted_average_val := 0;
330 
331       FOR l_kpi_colors IN c_kpi_colors(p_objective_color_rec.objective_id, p_objective_color_rec.tab_id, l_dim_comb.dim_comb) LOOP
332 
333         l_kpi_weight := get_kpi_measure_weight(p_objective_color_rec.objective_id, l_kpi_colors.kpi_measure_id);
334 
335         IF l_kpi_colors.kpi_color = BSC_COLOR_REPOSITORY.NO_COLOR AND l_kpi_weight <> 0 THEN
336           l_obj_color := BSC_COLOR_REPOSITORY.NO_COLOR;
337           l_set_no_color := TRUE;
338           EXIT;
339         END IF;
340 
341         l_num_eq := get_color_numeric_equivalent(l_kpi_colors.kpi_color);
342         l_result := (l_kpi_weight/100) * l_num_eq;
343         l_weighted_average_val := l_weighted_average_val + l_result;
344 
345       END LOOP;
346 
347       IF NOT l_set_no_color THEN
348         l_obj_color := get_weighted_obj_color( p_objective_color_rec.objective_id
349                                              , l_weighted_average_val
350                                              );
351         IF l_obj_color IS NULL THEN
352 	  RAISE e_unexpected_error;
353         END IF;
354       END IF;
355 
356       INSERT INTO bsc_sys_objective_colors
357         (tab_id, indicator, dim_level1, dim_level2, dim_level3, dim_level4, dim_level5, dim_level6, dim_level7, dim_level8, period_id, obj_color, driving_kpi_measure_id)
358         VALUES
359           (p_objective_color_rec.tab_id, p_objective_color_rec.objective_id,
360            l_dim_comb.dim_level1, l_dim_comb.dim_level2, l_dim_comb.dim_level3, l_dim_comb.dim_level4,
361            l_dim_comb.dim_level5, l_dim_comb.dim_level6, l_dim_comb.dim_level7, l_dim_comb.dim_level8,
362            l_dim_comb.period_id, l_obj_color, NULL);
363 
364     END IF;
365 
366   END LOOP;
367 
368   COMMIT;
369 
370   RETURN TRUE;
371 
372 EXCEPTION
373   WHEN e_unexpected_error THEN
374     ROLLBACK;
375     BSC_MESSAGE.Add(x_message => BSC_UPDATE_UTIL.Get_Message('BSC_KPICOLOR_FAILED'),
376                     x_source => 'BSC_COLOR_CALC_UTIL.Calc_Obj_Color_By_Weights');
377     RETURN FALSE;
378   WHEN OTHERS THEN
379     ROLLBACK;
380     BSC_MESSAGE.Add(x_message => SQLERRM,
381                     x_source => 'BSC_COLOR_CALC_UTIL.Calc_Obj_Color_By_Weights');
382     RETURN FALSE;
383 END Calc_Obj_Color_By_Weights;
384 
385 
386 FUNCTION get_weighted_obj_color (
387   p_pbjective_id      IN NUMBER
388 , p_weighted_avg_val  IN NUMBER
389 )
390 RETURN NUMBER IS
391   l_obj_color             NUMBER;
392   l_obj_color_method      NUMBER;
393   l_threshold_prop_table  threshold_prop_table;
394 BEGIN
395 
396   l_obj_color := BSC_COLOR_REPOSITORY.NO_COLOR;
397 
398   l_obj_color_method := get_objective_color_method(p_pbjective_id);
399 
400   l_threshold_prop_table := Get_Kpi_Measure_Threshold (p_pbjective_id, NULL);
401 
402   /*
403    * threshold_prop_table will be formulated as below:
404    *
405    * On the UI, user can enter values in any order of threshold values.
406    *
407    * INCREASING_GOOD :-
408    * The table of records will be ordered by the HIGH value of
409    * the color ranges in ascending order.
410    *
411    * threshold_prop_table:
412    * Operation		    Threshold               Color_Id
413    *  <=  			20			1
414    *  <=  			30			2
415    *  <=  			50			3
416    *  <=  			90			4
417    *  > 90 or ELSE  	        NULL			5
418    *
419    *
420    * DECREASING_GOOD OR WITHIN_RANGE:-
421    * The table of records will be ordered by the HIGH value of
422    * the color ranges in ascending order.
423    *
424    * threshold_prop_table:
425    * Operation		    Threshold               Color_Id
426    *  <  			20			1
427    *  < 			30			2
428    *  <  			50			3
429    *  <  			90			4
430    *  >= 90 or ELSE  	        NULL			5
431    */
432 
433   IF l_threshold_prop_table.COUNT > 0 THEN
434 
435     IF l_obj_color_method = 1 OR    -- INCREASING_GOOD
436        l_obj_color_method = 4 THEN  -- FLEXIBLE (not used today)
437 
438       FOR l_index IN 1..l_threshold_prop_table.COUNT LOOP
439 
440         IF l_threshold_prop_table(l_index).threshold IS NULL THEN
441 	  l_obj_color := l_threshold_prop_table(l_index).color_id;
442 	  EXIT;
443 	ELSIF p_weighted_avg_val <= l_threshold_prop_table(l_index).threshold THEN
444 	  l_obj_color := l_threshold_prop_table(l_index).color_id;
445 	  EXIT;
446         END IF;
447 
448       END LOOP;
449 
450     ELSIF l_obj_color_method = 2 OR    -- DECREASING_GOOD
451           l_obj_color_method = 3 THEN  -- WITHIN_RANGE
452 
453       FOR l_index IN 1..l_threshold_prop_table.COUNT LOOP
454 
455         IF l_threshold_prop_table(l_index).threshold IS NULL THEN
456           l_obj_color := l_threshold_prop_table(l_index).color_id;
457           EXIT;
458         ELSIF p_weighted_avg_val < l_threshold_prop_table(l_index).threshold THEN
459           l_obj_color := l_threshold_prop_table(l_index).color_id;
460           EXIT;
461         END IF;
462 
463       END LOOP;
464 
465     END IF;
466 
467   END IF;
468 
469   RETURN l_obj_color;
473     BSC_MESSAGE.Add(x_message => SQLERRM,
470 
471 EXCEPTION
472   WHEN OTHERS THEN
474                     x_source => 'BSC_COLOR_CALC_UTIL.get_weighted_obj_color');
475     RETURN NULL;
476 END get_weighted_obj_color;
477 
478 FUNCTION Get_Sim_Default_Kpi_Measure_Id (
479   p_objective_id  IN NUMBER
480 )
481 RETURN NUMBER IS
482 
483   CURSOR c_default_node_dataset(p_indicator NUMBER) IS
484     SELECT property_value dataset_id
485       FROM  bsc_kpi_properties
486       WHERE property_code = BSC_SIMULATION_VIEW_PUB.c_SIM_NODE_ID
487       AND   indicator = p_indicator;
488   l_default_node_dataset_id  bsc_kpi_properties.property_value%TYPE;
489 
490   CURSOR c_default_kpi(p_indicator NUMBER, p_dataset_id NUMBER) IS
491     SELECT kpi_measure_id
492       FROM bsc_kpi_analysis_measures_b anal_meas
493       WHERE anal_meas.dataset_id = p_dataset_id
494       AND   anal_meas.indicator = p_indicator;
495   l_default_kpi_rec  c_default_kpi%ROWTYPE;
496 
497   l_default_kpi_measure_id   bsc_kpi_measure_props.kpi_measure_id%TYPE;
498 
499 BEGIN
500 
501   l_default_kpi_measure_id := NULL;
502 
503   IF c_default_node_dataset%ISOPEN THEN
504     CLOSE c_default_node_dataset;
505   END IF;
506   OPEN c_default_node_dataset (p_objective_id);
507   FETCH c_default_node_dataset INTO l_default_node_dataset_id;
508   IF c_default_node_dataset%NOTFOUND THEN
509     RETURN NULL;
510   END IF;
511   CLOSE c_default_node_dataset;
512 
513   FOR l_default_kpi_rec IN c_default_kpi(p_objective_id, l_default_node_dataset_id) LOOP
514     -- Ideally only 1 row must be returned since duplicate datasets are not allowed in Simulation Objective
515     l_default_kpi_measure_id := l_default_kpi_rec.kpi_measure_id;
516   END LOOP;
517 
518   RETURN l_default_kpi_measure_id;
519 
520 EXCEPTION
521   WHEN OTHERS THEN
522     IF c_default_node_dataset%ISOPEN THEN
523       CLOSE c_default_node_dataset;
524     END IF;
525     BSC_MESSAGE.Add(x_message => SQLERRM,
526                     x_source => 'BSC_COLOR_CALC_UTIL.Get_Sim_Default_Kpi_Measure_Id');
527     RETURN NULL;
528 END Get_Sim_Default_Kpi_Measure_Id;
529 
530 
531 PROCEDURE Calc_Obj_Color_By_Single_Kpi (
532   p_objective_color_rec  IN BSC_UPDATE_COLOR.t_objective_color_rec
533  ,p_rollup_type          IN bsc_kpis_b.color_rollup_type%TYPE
534  ,x_kpi_measure_id       OUT NOCOPY NUMBER
535  ,x_color_flag           OUT NOCOPY BOOLEAN
536 
537 ) IS
538 
539   CURSOR c_dim_comb(p_indicator NUMBER, p_tab_id NUMBER) IS
540     SELECT DISTINCT
541            dim_level1 || dim_level2 || dim_level3 || dim_level4 || dim_level5 || dim_level6 || dim_level7 || dim_level8 || period_id dim_comb,
542            dim_level1, dim_level2, dim_level3, dim_level4, dim_level5, dim_level6, dim_level7, dim_level8,
543            period_id
544       FROM bsc_sys_kpi_colors
545       WHERE indicator = p_indicator
546       AND   tab_id = p_tab_id;
547   l_dim_comb  c_dim_comb%ROWTYPE;
548 
549   CURSOR c_kpi_colors(p_indicator NUMBER, p_tab_id NUMBER, p_dim_comb VARCHAR2) IS
550     SELECT kpi_color, kpi_measure_id
551       FROM bsc_sys_kpi_colors
552       WHERE dim_level1 || dim_level2 || dim_level3 || dim_level4 || dim_level5 || dim_level6 || dim_level7 || dim_level8 ||  period_id = p_dim_comb
553       AND   indicator = p_indicator
554       AND   tab_id = p_tab_id
555     UNION  -- bsc_sys_kpi_colors may not contain a color entry for 'color enabled' KPIs for which data has not been loaded
556     SELECT BSC_COLOR_REPOSITORY.NO_COLOR kpi_color, kpi_measure_id
557       FROM bsc_kpi_measure_props
558       WHERE indicator = p_indicator
559       AND   disable_color = 'F'
560       AND   kpi_measure_id NOT IN
561                            ( SELECT kpi_measure_id FROM bsc_sys_kpi_colors
562                              WHERE indicator = p_indicator
563                              AND   tab_id = p_tab_id
564                            );
565   l_kpi_colors  c_kpi_colors%ROWTYPE;
566 
567   e_unexpected_error        EXCEPTION;
568   l_default_kpi_measure_id  bsc_kpi_measure_props.kpi_measure_id%TYPE;
569   l_colors                  BSC_UPDATE_UTIL.t_array_of_number;
570   l_kpi_measures            BSC_UPDATE_UTIL.t_array_of_number;
571   l_color_index             NUMBER;
572   l_obj_color               NUMBER;
573   l_kpi_index               NUMBER := -1;
574 
575 BEGIN
576 
577   FOR l_dim_comb IN c_dim_comb(p_objective_color_rec.objective_id, p_objective_color_rec.tab_id) LOOP
578 
579     IF l_dim_comb.dim_comb IS NOT NULL THEN
580 
581       l_color_index := 0;
582       l_obj_color := BSC_COLOR_REPOSITORY.NO_COLOR;
583 
584       FOR l_kpi_colors IN c_kpi_colors(p_objective_color_rec.objective_id, p_objective_color_rec.tab_id, l_dim_comb.dim_comb) LOOP
585 
586         l_color_index := l_color_index + 1;
587         l_colors(l_color_index) := l_kpi_colors.kpi_color;
588         l_kpi_measures(l_color_index) := l_kpi_colors.kpi_measure_id;
589 
590       END LOOP;
591 
592       get_rollup_obj_color( p_rollup_type => p_rollup_type
593                           , p_colors      => l_colors
594                           , p_num_colors  => l_color_index
595                           , x_color       => l_obj_color
596                           , x_kpi_index   => l_kpi_index
597                           );
598 
599       IF l_obj_color IS NULL THEN
600         RAISE e_unexpected_error;
601       END IF;
602 
603       IF l_kpi_index >= 0 THEN
604         x_kpi_measure_id := l_kpi_measures(l_kpi_index);
605       ELSE
609       INSERT INTO bsc_sys_objective_colors
606         x_kpi_measure_id := -1;
607       END IF;
608 
610         (tab_id, indicator, dim_level1, dim_level2, dim_level3, dim_level4, dim_level5, dim_level6, dim_level7, dim_level8, period_id, obj_color, driving_kpi_measure_id)
611         VALUES
612           (p_objective_color_rec.tab_id, p_objective_color_rec.objective_id,
613            l_dim_comb.dim_level1, l_dim_comb.dim_level2, l_dim_comb.dim_level3, l_dim_comb.dim_level4,
614            l_dim_comb.dim_level5, l_dim_comb.dim_level6, l_dim_comb.dim_level7, l_dim_comb.dim_level8,
615            l_dim_comb.period_id, l_obj_color, x_kpi_measure_id);
616 
617     END IF;
618 
619   END LOOP;
620 
621   COMMIT;
622 
623   x_color_flag     := TRUE;
624   --RETURN TRUE;
625 
626 EXCEPTION
627   WHEN e_unexpected_error THEN
628     ROLLBACK;
629     BSC_MESSAGE.Add(x_message => BSC_UPDATE_UTIL.Get_Message('BSC_KPICOLOR_FAILED'),
630                     x_source => 'BSC_COLOR_CALC_UTIL.Calc_Obj_Color_By_Single_Kpi');
631     x_kpi_measure_id := -1;
632     x_color_flag     := false;
633     --RETURN FALSE;
634   WHEN OTHERS THEN
635     ROLLBACK;
636     BSC_MESSAGE.Add(x_message => SQLERRM,
637                     x_source => 'BSC_COLOR_CALC_UTIL.Calc_Obj_Color_By_Single_Kpi');
638     x_kpi_measure_id := -1;
639     x_color_flag     := false;
640     --RETURN FALSE;
641 END Calc_Obj_Color_By_Single_Kpi;
642 
643 
644 /* Returns the worst color out of all the colors in the input array.
645  * Worst color is based on BSC_SYS_COLORS_B.PERF_SEQUENCE.
646  * If any of the KPI colors passed in is GRAY or NO_COLOR, color that
647  * will be returned will also be GRAY.
648 */
649 PROCEDURE get_worst_color (
650   p_colors      IN BSC_UPDATE_UTIL.t_array_of_number
651 , p_num_colors  IN NUMBER
652 , x_color       OUT NOCOPY NUMBER
653 , x_kpi_index   OUT NOCOPY NUMBER
654 ) IS
655 
656   l_index         NUMBER;
657   l_max_perf_seq  NUMBER;
658   l_perf_seq      NUMBER;
659   l_worst_color   BSC_SYS_COLORS_B.color_id%TYPE;
660 
661 BEGIN
662 
663   IF p_num_colors = 0 THEN
664 
665     x_color := BSC_COLOR_REPOSITORY.NO_COLOR;
666     x_kpi_index := -1;
667 
668   ELSIF p_num_colors = 1 THEN
669 
670     x_color := p_colors(1);
671     x_kpi_index := 1;
672 
673   ELSE
674 
675     l_max_perf_seq := get_color_perf_seq(p_colors(1));
676     l_worst_color := p_colors(1);
677     x_kpi_index   := 1;
678 
679     FOR l_index IN 1 .. p_num_colors LOOP
680       -- we could have started counter from 2, but we are doing from 1 since we want
681       -- to check for NO_COLOR for the first color p_colors(1) also.
682 
683       IF p_colors(l_index) = BSC_COLOR_REPOSITORY.NO_COLOR THEN
684         x_color := BSC_COLOR_REPOSITORY.NO_COLOR;
685         x_kpi_index := l_index;
686         RETURN;
687       END IF;
688 
689       l_perf_seq := get_color_perf_seq(p_colors(l_index));
690       IF l_max_perf_seq < l_perf_seq THEN
691         l_max_perf_seq := l_perf_seq;
692         l_worst_color  := p_colors(l_index);
693         x_kpi_index    := l_index;
694       END IF;
695 
696     END LOOP;
697 
698     x_color := l_worst_color;
699 
700   END IF;
701 
702 EXCEPTION
703   WHEN OTHERS THEN
704     BSC_MESSAGE.Add(x_message => SQLERRM,
705                     x_source => 'BSC_COLOR_CALC_UTIL.get_worst_color');
706     --RETURN NULL;
707 END get_worst_color;
708 
709 /* Returns the best color out of all the colors in the input array.
710  * Best color is based on BSC_SYS_COLORS_B.PERF_SEQUENCE.
711  * If any of the KPI colors passed in is GRAY or NO_COLOR, color that
712  * will be returned will also be GRAY.
713 */
714 PROCEDURE get_best_color (
715   p_colors      IN BSC_UPDATE_UTIL.t_array_of_number
716 , p_num_colors  IN NUMBER
717 , x_color       OUT NOCOPY NUMBER
718 , x_kpi_index OUT NOCOPY NUMBER
719 ) IS
720 
721   l_index         NUMBER;
722   l_min_perf_seq  NUMBER;
723   l_perf_seq      NUMBER;
724   l_best_color    BSC_SYS_COLORS_B.color_id%TYPE;
725 
726 BEGIN
727 
728   IF p_num_colors = 0 THEN
729 
730     x_color := BSC_COLOR_REPOSITORY.NO_COLOR;
731     x_kpi_index := -1;
732     RETURN;
733 
734   ELSIF p_num_colors = 1 THEN
735 
736     x_color := p_colors(1);
737     x_kpi_index := 1;
738     RETURN;
739   ELSE
740 
741     l_min_perf_seq := get_color_perf_seq(p_colors(1));
742     l_best_color := p_colors(1);
746       -- we could have started counter from 2, but we are doing from 1 since we want
743     x_kpi_index  := 1;
744 
745     FOR l_index IN 1 .. p_num_colors LOOP
747       -- to check for NO_COLOR for the first color p_colors(1) also.
748 
749       IF p_colors(l_index) = BSC_COLOR_REPOSITORY.NO_COLOR THEN
750         x_color := BSC_COLOR_REPOSITORY.NO_COLOR;
751         x_kpi_index := l_index;
752         RETURN;
753       END IF;
754 
755       l_perf_seq := get_color_perf_seq(p_colors(l_index));
756       IF l_min_perf_seq > l_perf_seq THEN
757         l_min_perf_seq := l_perf_seq;
758         l_best_color := p_colors(l_index);
759         x_kpi_index := l_index;
760       END IF;
761 
762     END LOOP;
763 
764     x_color := l_best_color;
765     RETURN;
766 
767   END IF;
768 
769 EXCEPTION
770   WHEN OTHERS THEN
771     ROLLBACK;
772     BSC_MESSAGE.Add(x_message => SQLERRM,
773                     x_source => 'BSC_COLOR_CALC_UTIL.get_best_color');
774     --RETURN NULL;
775 END get_best_color;
776 
777 
778 PROCEDURE get_colors_with_max_count (
779   p_array_of_number  IN BSC_UPDATE_UTIL.t_array_of_number
780 , p_max_count        IN NUMBER
781 , p_colors_array     OUT NOCOPY BSC_UPDATE_UTIL.t_array_of_number
782 , p_color_count      OUT NOCOPY NUMBER
783 )
784 IS
785   l_index         NUMBER;
786   l_array_colors  BSC_COLOR_REPOSITORY.t_array_colors;
787   l_color_rec     BSC_COLOR_REPOSITORY.t_color_rec;
788 
789 BEGIN
790 
791   p_color_count := 0;
792   l_array_colors := BSC_COLOR_REPOSITORY.get_color_props();
793   FOR l_index IN 1 .. l_array_colors.COUNT LOOP
794     l_color_rec := l_array_colors(l_index);
795 
796     IF p_array_of_number(l_color_rec.color_id) = p_max_count THEN
797       p_color_count := p_color_count + 1;
798       p_colors_array(p_color_count) := l_color_rec.color_id;
799     END IF;
800 
801   END LOOP;
802 
803 EXCEPTION
804   WHEN OTHERS THEN
805     NULL;
806 END get_colors_with_max_count;
807 
808 
809 /* Returns the color which occurs maximum number of times out of all
810  * the colors in the input array. If 2 or more colors have the same number
811  * of occurences, then the worst color of those will be returned.
812  * If any of the KPI colors passed in is GRAY or NO_COLOR, color that
813  * will be returned will also be GRAY.
814 */
815 PROCEDURE get_most_frequent_color (
816   p_colors      IN BSC_UPDATE_UTIL.t_array_of_number
817 , p_num_colors  IN NUMBER
818 , x_color       OUT NOCOPY NUMBER
819 , x_kpi_index   OUT NOCOPY NUMBER
820 ) IS
821 
822   l_index            NUMBER;
823   l_min_perf_seq     NUMBER;
824   l_perf_seq         NUMBER;
825   l_most_freq_color  BSC_SYS_COLORS_B.color_id%TYPE;
826   l_array_of_number  BSC_UPDATE_UTIL.t_array_of_number;
827   l_colors_array     BSC_UPDATE_UTIL.t_array_of_number;
828   l_color_count      NUMBER;
829   l_max_count        NUMBER;
830   i NUMBER;
831 BEGIN
832 
833   IF p_num_colors = 0 THEN
834 
835     x_color := BSC_COLOR_REPOSITORY.NO_COLOR;
836     x_kpi_index := -1;
837 
838   ELSIF p_num_colors = 1 THEN
839 
840     x_color := p_colors(1);
841     x_kpi_index := 1;
842 
843   ELSE
844 
845     l_most_freq_color := BSC_COLOR_REPOSITORY.NO_COLOR;
846     x_kpi_index       := -1;
847     initialize_color_array(l_array_of_number);
848 
849     FOR l_index IN 1 .. p_num_colors LOOP
850 
851       IF p_colors(l_index) = BSC_COLOR_REPOSITORY.NO_COLOR THEN
852         x_color := BSC_COLOR_REPOSITORY.NO_COLOR;
853         x_kpi_index := l_index;
854         RETURN;
855       END IF;
856 
857 
858       IF l_array_of_number(p_colors(l_index)) > 0 THEN
859         l_array_of_number(p_colors(l_index)) := l_array_of_number(p_colors(l_index)) + 1;
860       ELSE
861         l_array_of_number(p_colors(l_index)) := 1;
862       END IF;
863 
864     END LOOP;
865 
866     l_max_count := get_max_count(l_array_of_number);
867 
868     get_colors_with_max_count(l_array_of_number
869                             , l_max_count
870                             , l_colors_array
871                             , l_color_count);
872 
873 
874 
875     IF(l_color_count=1 and l_max_count > 1) THEN
876        x_color := l_colors_array(1);
877        FOR i in 1..p_colors.COUNT LOOP
878           if( p_colors(i)=x_color) THEN
879              x_kpi_index := i;
880              EXIT;
881            END IF;
882         END LOOP;
883 
884 
885     ELSE
886              FOR i IN REVERSE 1..l_colors_array.COUNT LOOP
887                x_color := l_colors_array(i);
888                EXIT;
889              END LOOP;
890              FOR i IN 1..p_colors.COUNT LOOP
891                 IF(p_colors(i)=x_color) THEN
892                    x_kpi_index := i;
893                    EXIT;
894                 END IF;
895              END LOOP;
896    END IF;
897   END IF;
898 
899 EXCEPTION
900   WHEN OTHERS THEN
901     BSC_MESSAGE.Add(x_message => SQLERRM,
902                     x_source => 'BSC_COLOR_CALC_UTIL.get_most_frequent_color');
903     --RETURN NULL;
904 END get_most_frequent_color;
905 
906 
907 PROCEDURE get_rollup_obj_color (
908   p_rollup_type IN bsc_kpis_b.color_rollup_type%TYPE
909 , p_colors      IN BSC_UPDATE_UTIL.t_array_of_number
910 , p_num_colors  IN NUMBER
911 , x_color       OUT NOCOPY NUMBER
912 , x_kpi_index   OUT NOCOPY NUMBER
913 ) IS
914 BEGIN
915   IF p_rollup_type = BEST THEN
916     get_best_color(p_colors, p_num_colors, x_color, x_kpi_index);
917   ELSIF p_rollup_type = WORST THEN
918     get_worst_color(p_colors, p_num_colors, x_color, x_kpi_index);
919   ELSIF p_rollup_type = MOST_FREQUENT THEN
920     get_most_frequent_color(p_colors, p_num_colors, x_color, x_kpi_index);
921   END IF;
922 EXCEPTION
923   WHEN OTHERS THEN
924     BSC_MESSAGE.Add(x_message => SQLERRM,
925                     x_source => 'BSC_COLOR_CALC_UTIL.get_rollup_obj_color');
926     --RETURN NULL;
927 END get_rollup_obj_color;
928 
929 
930 FUNCTION Get_Default_Kpi_Measure_Id (
931   p_objective_id  IN NUMBER
932 )
933 RETURN NUMBER IS
934 
935   CURSOR c_default_kpi(p_indicator NUMBER) IS
936     SELECT m.kpi_measure_id
937       FROM bsc_db_dataset_dim_sets_v m,
938            bsc_db_color_ao_defaults_v d
939       WHERE m.indicator = d.indicator
940       AND   m.a0 = d.a0_default
941       AND   m.a1 = d.a1_default
942       AND   m.a2 = d.a2_default
943       AND   m.default_value = 1
944       AND   m.indicator = p_indicator;
945 
946   l_default_kpi_measure_id  bsc_kpi_measure_props.kpi_measure_id%TYPE;
947 
948 BEGIN
949 
950   l_default_kpi_measure_id := NULL;
951 
952   IF c_default_kpi%ISOPEN THEN
953     CLOSE c_default_kpi;
954   END IF;
955   OPEN c_default_kpi (p_objective_id);
956   FETCH c_default_kpi INTO l_default_kpi_measure_id;
957   IF c_default_kpi%NOTFOUND THEN
958     RETURN NULL;
959   END IF;
960   CLOSE c_default_kpi;
961 
962   RETURN l_default_kpi_measure_id;
963 
964 EXCEPTION
965   WHEN OTHERS THEN
966     IF c_default_kpi%ISOPEN THEN
967       CLOSE c_default_kpi;
968     END IF;
969     BSC_MESSAGE.Add(x_message => SQLERRM,
970                     x_source => 'BSC_COLOR_CALC_UTIL.Get_Default_Kpi_Measure_Id');
971     RETURN NULL;
972 END Get_Default_Kpi_Measure_Id;
973 
974 
975 PROCEDURE Calc_Obj_Color_By_Default_Kpi (
976   p_objective_color_rec  IN BSC_UPDATE_COLOR.t_objective_color_rec
977  ,x_kpi_measure_id       OUT NOCOPY NUMBER
978  ,x_color_flag           OUT NOCOPY BOOLEAN
979 ) IS
980 
981   l_default_kpi_measure_id  bsc_kpi_measure_props.kpi_measure_id%TYPE;
982 
983 BEGIN
984 
985   IF p_objective_color_rec.sim_flag THEN -- Simulation Objective
986     l_default_kpi_measure_id := Get_Sim_Default_Kpi_Measure_Id(p_objective_color_rec.objective_id);
987   ELSE
988     l_default_kpi_measure_id := Get_Default_Kpi_Measure_Id(p_objective_color_rec.objective_id);
989   END IF;
990 
991   IF l_default_kpi_measure_id IS NULL THEN
992     RAISE FND_API.G_EXC_ERROR;
993   END IF;
994 
995   INSERT /*+ append */
996     INTO bsc_sys_objective_colors
997     (tab_id, indicator, dim_level1, dim_level2, dim_level3, dim_level4, dim_level5, dim_level6, dim_level7, dim_level8, period_id, obj_color, driving_kpi_measure_id)
998       SELECT tab_id, indicator, dim_level1, dim_level2, dim_level3, dim_level4, dim_level5, dim_level6, dim_level7, dim_level8, period_id, kpi_color, kpi_measure_id
999         FROM bsc_sys_kpi_colors
1000         WHERE kpi_measure_id = l_default_kpi_measure_id
1001         AND   tab_id = p_objective_color_rec.tab_id
1002         AND   indicator = p_objective_color_rec.objective_id;
1003 
1004   COMMIT;
1005 
1006   x_kpi_measure_id := l_default_kpi_measure_id;
1007   x_color_flag     := true;
1008 
1009 EXCEPTION
1010   WHEN OTHERS THEN
1011     ROLLBACK;
1012     BSC_MESSAGE.Add(x_message => SQLERRM,
1013                     x_source => 'BSC_COLOR_CALC_UTIL.Calc_Obj_Color_By_Default_Kpi');
1014     x_color_flag     := false;
1015     x_kpi_measure_id := -1;
1016     --RETURN FALSE;
1017 END Calc_Obj_Color_By_Default_Kpi;
1018 
1019 
1020 FUNCTION Get_Obj_Color_Rollup_Type (
1021   p_objective_id  IN NUMBER
1022 )
1023 RETURN VARCHAR2 IS
1024 
1025   CURSOR c_rollup_type(p_indicator NUMBER) IS
1026     SELECT color_rollup_type
1027       FROM bsc_kpis_b
1028       WHERE indicator = p_indicator;
1029 
1030   l_rollup_type  bsc_kpis_b.color_rollup_type%TYPE;
1031 
1032 BEGIN
1033 
1034   l_rollup_type := NULL;
1035 
1036   IF p_objective_id IS NOT NULL THEN
1037     IF c_rollup_type%ISOPEN THEN
1038       CLOSE c_rollup_type;
1039     END IF;
1040     OPEN c_rollup_type (p_objective_id);
1041     FETCH c_rollup_type INTO l_rollup_type;
1042     IF c_rollup_type%NOTFOUND THEN
1043       RETURN NULL;
1044     END IF;
1045     CLOSE c_rollup_type;
1046   END IF;
1047 
1048   RETURN l_rollup_type;
1049 
1050 EXCEPTION
1051   WHEN OTHERS THEN
1052     IF c_rollup_type%ISOPEN THEN
1053       CLOSE c_rollup_type;
1054     END IF;
1055     BSC_MESSAGE.Add(x_message => SQLERRM,
1056                     x_source  => 'BSC_COLOR_CALC_UTIL.Get_Obj_Color_Rollup_Type');
1057     RETURN NULL;
1058 END Get_Obj_Color_Rollup_Type;
1059 
1060 END BSC_COLOR_CALC_UTIL;