DBA Data[Home] [Help]

PACKAGE BODY: APPS.PSB_BUDGET_POSITION_PVT

Source


1 PACKAGE BODY PSB_Budget_Position_Pvt AS
2 /* $Header: PSBVMBPB.pls 120.3 2005/10/14 17:05:06 matthoma ship $ */
3 
4   G_PKG_NAME CONSTANT VARCHAR2(30 ):=  'PSB_Budget_Position_Pvt';
5 
6 
7 /*-------------------- Global variables and declarations --------------------*/
8 
9   -- The flag determines whether to print debug information or not.
10   g_debug_flag           VARCHAR2(1) := 'N' ;
11 
12   -- Record type to store a position_set_line and a position.
13   TYPE position_rec_type IS RECORD
14 			 (  line_sequence_id NUMBER,
15 			    position_id      NUMBER
16 			    );
17 
18   -- Table type to store position_set_lines and positions for a position set.
19   TYPE position_set_tbl_type IS TABLE OF position_rec_type
20        INDEX BY BINARY_INTEGER;
21 
22   -- Global Table to store position_set_lines and positions for a position set.
23   l_position_set_tbl           position_set_tbl_type ;
24 
25   -- Table type to store positions.
26   TYPE position_tbl_type IS TABLE OF NUMBER
27        INDEX BY BINARY_INTEGER;
28 
29   -- To store current position set id.
30   g_position_set_id
31 		   psb_account_position_sets.account_position_set_id%TYPE;
32 
33   --
34   -- WHO columns variables
35   --
36   g_current_date           DATE   := sysdate                     ;
37   g_current_user_id        NUMBER := NVL(Fnd_Global.User_Id , 0) ;
38   g_current_login_id       NUMBER := NVL(Fnd_Global.Login_Id, 0) ;
39 
40 /*----------------------- End Private variables -----------------------------*/
41 
42 
43 
44 /* ---------------------- Private Routine prototypes  -----------------------*/
45 
46      PROCEDURE Init;
47      --
48      FUNCTION Populate_Budget_Position_Set
49 	      (
50 		 p_position_set_id           IN  NUMBER  ,
51 		 p_attribute_selection_type  IN  VARCHAR2
52 	       )
53 	      RETURN BOOLEAN ;
54 
55      PROCEDURE  pd
56 	      (
57 		 p_message                   IN  VARCHAR2
58 	       ) ;
59 
60 /* ------------------ End Private Routines prototypes  ----------------------*/
61 
62 
63 
64 /*===========================================================================+
65  |                     PROCEDURE Populate_Budget_Positions                   |
66  +===========================================================================*/
67 --
68 -- The Public API to maintain positions for position sets.
69 --
70 PROCEDURE Populate_Budget_Positions
71 (
72   p_api_version       IN       NUMBER ,
73   p_init_msg_list     IN       VARCHAR2 := FND_API.G_FALSE ,
74   p_commit            IN       VARCHAR2 := FND_API.G_FALSE ,
75   p_validation_level  IN       NUMBER   := FND_API.G_VALID_LEVEL_FULL ,
76   p_return_status     OUT  NOCOPY      VARCHAR2 ,
77   p_msg_count         OUT  NOCOPY      NUMBER ,
78   p_msg_data          OUT  NOCOPY      VARCHAR2 ,
79   --
80   p_position_set_id   IN  psb_account_position_sets.account_position_set_id%TYPE
81 			  := FND_API.G_MISS_NUM ,
82 
83   p_data_extract_id   IN  psb_data_extracts.data_extract_id%TYPE
84 			  := FND_API.G_MISS_NUM
85 )
86 IS
87   --
88   l_api_name            CONSTANT VARCHAR2(30)   := 'Populate_Budget_Positions';
89   l_api_version         CONSTANT NUMBER         :=  1.0;
90   --
91   l_attribute_selection_type
92 		     psb_account_position_sets.attribute_selection_type%TYPE ;
93   l_data_extract_id  psb_data_extracts.data_extract_id%TYPE ;
94   --
95 BEGIN
96   --
97   SAVEPOINT Populate_Budget_Positions_Pvt ;
98   --
99   IF NOT FND_API.Compatible_API_Call ( l_api_version,
100 				       p_api_version,
101 				       l_api_name,
102 				       G_PKG_NAME )
103   THEN
104     RAISE FND_API.G_EXC_UNEXPECTED_ERROR ;
105   END IF;
106   --
107 
108   IF FND_API.to_Boolean ( p_init_msg_list ) THEN
109     FND_MSG_PUB.initialize ;
110   END IF;
111   --
112   p_return_status := FND_API.G_RET_STS_SUCCESS ;
113   --
114 
115   --
116   -- As FND_API.G_MISS_NUM is bigger than NUMBERR(15), now using a local
117   -- variable to fis the bug #655442.
118   --
119   IF p_data_extract_id = FND_API.G_MISS_NUM THEN
120     l_data_extract_id := NULL;
121   ELSE
122     l_data_extract_id := p_data_extract_id ;
123   END IF;
124 
125   IF ( p_position_set_id = FND_API.G_MISS_NUM ) OR ( p_position_set_id IS NULL)
126   THEN
127     --
128     -- As no parameter is supplied, we have to populate all the position
129     -- sets in psb_account_position_sets table.
130     --
131     FOR l_set_rec IN
132     (
133       SELECT account_position_set_id ,
134 	     attribute_selection_type
135       FROM   psb_account_position_sets
136       WHERE  account_or_position_type = 'P'
137       AND    data_extract_id = NVL( l_data_extract_id, data_extract_id )
138     )
139     LOOP
140       --
141       -- Perform initilization. To be done for each position set.
142       --
143       Init;
144 
145       --
146       -- Call the Populate_Budget_Position_Set routine for each position set.
147       --
148       IF Populate_Budget_Position_Set
149 	 (
150 	    l_set_rec.account_position_set_id  ,
151 	    l_set_rec.attribute_selection_type
152 	 )
153       THEN
154 	--
155 	-- The concurrent program is the only one which calls  the API
156 	-- without any argument. We need to release lock as soon as an
157 	-- position set is exploded. Committing will also ensure that
158 	-- rollback segments do not go out of bounds.
159 	--
160 	COMMIT WORK;
161 	--
162 	-- Re-establish the savepoint after the commit.
163 	SAVEPOINT Populate_Budget_Positions_Pvt ;
164 	--
165       ELSE
166 	--
167 	RAISE FND_API.G_EXC_UNEXPECTED_ERROR ;
168 	--
169       END IF;
170       --
171     END LOOP;
172     --
173   ELSE
174     --
175     -- Only the passed position set will be populated.
176     -- Perform initilization for this set.
177     --
178     Init;
179 
180 
181     --
182     -- Find attribute_selection_type for the given set.
183     --
184     SELECT attribute_selection_type INTO l_attribute_selection_type
185     FROM   psb_account_position_sets
186     WHERE  account_position_set_id = p_position_set_id ;
187 
188     --
189     -- Call Populate_Budget_Position_Set only for the given position set.
190     --
191     IF NOT Populate_Budget_Position_Set
192 	   (
193 	      p_position_set_id          ,
194 	      l_attribute_selection_type
195 	   )
196     THEN
197       RAISE FND_API.G_EXC_UNEXPECTED_ERROR ;
198     END IF;
199   END IF;
200 
201   --
202   IF FND_API.To_Boolean ( p_commit ) THEN
203     COMMIT WORK;
204   END IF;
205   --
206   FND_MSG_PUB.Count_And_Get ( p_count => p_msg_count,
207 			      p_data  => p_msg_data );
208   --
209 EXCEPTION
210   --
211   WHEN FND_API.G_EXC_ERROR THEN
212     --
213     ROLLBACK TO Populate_Budget_Positions_Pvt ;
214     p_return_status := FND_API.G_RET_STS_ERROR;
215     FND_MSG_PUB.Count_And_Get ( p_count => p_msg_count,
216 				p_data  => p_msg_data );
217   --
218   WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
219     --
220     ROLLBACK TO Populate_Budget_Positions_Pvt ;
221     p_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
222     FND_MSG_PUB.Count_And_Get ( p_count => p_msg_count,
223 				p_data  => p_msg_data );
224   --
225   WHEN OTHERS THEN
226     --
227     ROLLBACK TO Populate_Budget_Positions_Pvt ;
228     p_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
229     --
230     IF FND_MSG_PUB.Check_Msg_Level (FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
231       FND_MSG_PUB.Add_Exc_Msg ( G_PKG_NAME,
232 				l_api_name);
233     END if;
234     --
235     FND_MSG_PUB.Count_And_Get ( p_count => p_msg_count,
236 				p_data  => p_msg_data );
237      --
238 END Populate_Budget_Positions ;
239 /*---------------------------------------------------------------------------*/
240 
241 
242 
243 /*===========================================================================+
244  |                    PROCEDURE Add_Position_To_Position_Sets                |
245  +===========================================================================*/
246 --
247 -- This API finds all the position sets a position belongs to, and the adds
248 -- this information in psb_budget_positions table.
249 --
250 PROCEDURE Add_Position_To_Position_Sets
251 (
252   p_api_version         IN    NUMBER ,
253   p_init_msg_list       IN    VARCHAR2 := FND_API.G_FALSE ,
254   p_commit              IN    VARCHAR2 := FND_API.G_FALSE ,
255   p_validation_level    IN    NUMBER   := FND_API.G_VALID_LEVEL_FULL ,
256   p_return_status       OUT  NOCOPY   VARCHAR2 ,
257   p_msg_count           OUT  NOCOPY   NUMBER   ,
258   p_msg_data            OUT  NOCOPY   VARCHAR2 ,
259   --
260   p_position_id         IN    psb_positions.position_id%TYPE,
261   p_worksheet_id        IN    NUMBER
262 )
263 IS
264   --
265   l_api_name             CONSTANT VARCHAR2(30):='Add_Position_To_Position_Sets';
266   l_api_version          CONSTANT NUMBER      :=  1.0;
267   --
268   l_data_extract_id             psb_positions.data_extract_id%TYPE ;
269   l_business_group_id           psb_positions.data_extract_id%TYPE ;
270   l_match_found_in_set_flag     VARCHAR2(1) ;
271   l_matching_attributes_count   NUMBER ;
272   --
273 BEGIN
274   --
275   SAVEPOINT Add_Position_To_Pos_Sets_Pvt ;
276   --
277   IF NOT FND_API.Compatible_API_Call ( l_api_version,
278 				       p_api_version,
279 				       l_api_name,
280 				       G_PKG_NAME )
281   THEN
282     RAISE FND_API.G_EXC_UNEXPECTED_ERROR ;
283   END IF;
284   --
285 
286   IF FND_API.to_Boolean ( p_init_msg_list ) THEN
287     FND_MSG_PUB.initialize ;
288   END IF;
289   --
290 
291   p_return_status := FND_API.G_RET_STS_SUCCESS ;
292 
293   --
294   -- Find information about the position.
295   --
296   SELECT data_extract_id     ,
297 	 business_group_id
298        INTO
299 	 l_data_extract_id   ,
300 	 l_business_group_id
301   FROM   psb_positions
302   WHERE  position_id = p_position_id ;
303 
304   -- Scan all the position sets to check which one the position belongs to.
305   FOR l_set_rec IN
306   (
307      SELECT account_position_set_id ,
308 	    attribute_selection_type
309      FROM   psb_account_position_sets
310      WHERE  account_or_position_type = 'P'
311      AND    data_extract_id          = l_data_extract_id
312   )
313   LOOP
314 
315     pd('The current set ' || l_set_rec.account_position_set_id );
316 
317     --
318     -- Re-intilialize the flag for each set.
319     -- ( Based on the set type and the processing logic )
320     --
321     IF l_set_rec.attribute_selection_type = 'A' THEN
322 
323       l_match_found_in_set_flag := 'Y' ;
324 
325     ELSIF l_set_rec.attribute_selection_type = 'O' THEN
326 
327       l_match_found_in_set_flag := 'N' ;
328 
329     END IF;
330 
331     -- Get all the set lines for the current set. We have to evaluate each
332     -- set line and their associated values for the attribute_selection_type.
333     FOR l_set_lines_rec IN
334     (
335        SELECT line_sequence_id, attribute_id
336        FROM   psb_account_position_set_lines
337        WHERE  account_position_set_id = l_set_rec.account_position_set_id
338      )
339     LOOP
340 
341       pd('Attribute id ' || l_set_lines_rec.attribute_id );
342 
343       -- Check whether the position belongs to the current set.
344       SELECT COUNT(*) INTO l_matching_attributes_count
345       FROM   psb_position_assignments      asgn ,
346 	     psb_position_set_line_values  vals
347       WHERE  vals.line_sequence_id = l_set_lines_rec.line_sequence_id
348       AND    asgn.position_id      = p_position_id
349       AND    asgn.attribute_id     = l_set_lines_rec.attribute_id
350       AND    (
351 	       asgn.attribute_value_id = vals.attribute_value_id
352 	       OR
353 	       asgn.attribute_value    = vals.attribute_value
354 	      )
355       /* Bug 4545909 Start */
356       AND ((worksheet_id IS NULL AND NOT EXISTS
357            (SELECT 1 FROM psb_position_assignments
358              WHERE worksheet_id = p_worksheet_id
359                AND attribute_id = asgn.attribute_id
360                AND position_id  = asgn.position_id))
361                 OR worksheet_id = p_worksheet_id
362                 OR (worksheet_id IS NULL AND p_worksheet_id IS NULL))
363                AND ROWNUM < 2 ;
364       /* Bug 4545909 End */
365 
366       IF l_set_rec.attribute_selection_type = 'A' THEN
367 
368 	IF l_matching_attributes_count = 0 THEN
369 
370 	  -- The position does not belong to the current position set.
371 	  -- ( The position needs to belong to every set line. )
372 	  l_match_found_in_set_flag := 'N';
373 	  EXIT;
374 	END IF;
375 
376       ELSIF l_set_rec.attribute_selection_type = 'O' THEN
377 
378 	IF l_matching_attributes_count > 0 THEN
379 
383 	  EXIT;
380 	  -- The position belongs to the current position set.
381 	  -- ( The position needs to belong to any set line. )
382 	  l_match_found_in_set_flag := 'Y';
384 
385 	END IF;
386 
387       END IF;
388 
389     END LOOP; -- End processing the current account set.
390 
391     pd('Found flag ' || l_match_found_in_set_flag );
392 
393     -- If match found, put the information in psb_budget_positions table.
394     IF l_match_found_in_set_flag = 'Y' THEN
395       INSERT INTO psb_budget_positions
396 		  (
397 		     account_position_set_id            ,
398 		     position_id                        ,
399 		     data_extract_id                    ,
400 		     business_group_id                  ,
401 		     last_update_date                   ,
402 		     last_update_login                  ,
403 		     last_updated_by                    ,
404 		     created_by                         ,
405 		     creation_date
406 		  )
407 	    SELECT   l_set_rec.account_position_set_id  ,
408 		     p_position_id                      ,
409 		     l_data_extract_id                  ,
410 		     l_business_group_id                ,
411 		     g_current_date                     ,
412 		     g_current_login_id                 ,
413 		     g_current_user_id                  ,
414 		     g_current_user_id                  ,
415 		     g_current_date
416 	    FROM     dual
417 	    WHERE    NOT EXISTS
418 		     (  SELECT '1'
419 			FROM   psb_budget_positions
420 			WHERE  account_position_set_id
421 					    = l_set_rec.account_position_set_id
422 			AND    position_id  = p_position_id
423 		     ) ;
424       --
425     END IF;
426 
427   END LOOP; -- End processing all the sets.
428 
429 
430   --
431   IF FND_API.To_Boolean ( p_commit ) THEN
432     COMMIT WORK;
433   END IF;
434   --
435   FND_MSG_PUB.Count_And_Get ( p_count => p_msg_count,
436 			      p_data  => p_msg_data );
437   --
438 EXCEPTION
439   --
440   WHEN FND_API.G_EXC_ERROR THEN
441     --
442     ROLLBACK TO Add_Position_To_Pos_Sets_Pvt ;
443     p_return_status := FND_API.G_RET_STS_ERROR;
444     FND_MSG_PUB.Count_And_Get ( p_count => p_msg_count,
445 				p_data  => p_msg_data );
446   --
447   WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
448     --
449     ROLLBACK TO Add_Position_To_Pos_Sets_Pvt ;
450     p_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
451     FND_MSG_PUB.Count_And_Get ( p_count => p_msg_count,
452 				p_data  => p_msg_data );
453   --
454   WHEN OTHERS THEN
455     --
456     ROLLBACK TO Add_Position_To_Pos_Sets_Pvt ;
457     p_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
458     --
459     IF FND_MSG_PUB.Check_Msg_Level (FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
460       FND_MSG_PUB.Add_Exc_Msg ( G_PKG_NAME,
461 				l_api_name);
462     END if;
463     --
464     FND_MSG_PUB.Count_And_Get ( p_count => p_msg_count,
465 				p_data  => p_msg_data );
466      --
467 END Add_Position_To_Position_Sets ;
468 /*---------------------------------------------------------------------------*/
469 
470 
471 
472 /*===========================================================================+
473  |                     PROCEDURE Init (Private)                              |
474  +===========================================================================*/
475 --
476 -- Private procedure to perform variable initilization.
477 --
478 PROCEDURE Init
479 IS
480 --
481 BEGIN
482   --
483   -- Re-initialize dates as the concurrent program may be run for days.
484   --
485   g_current_date := sysdate ;
486 
487 END Init;
488 /*---------------------------------------------------------------------------*/
489 
490 
491 
492 /*===========================================================================+
493  |            FUNCTION  Populate_Budget_Position_Set (Private)               |
494  +===========================================================================*/
495 --
496 -- This Private function is to populate a given position set.
497 --
498 FUNCTION Populate_Budget_Position_Set
499 (
500    p_position_set_id           IN  NUMBER   ,
501    p_attribute_selection_type  IN  VARCHAR2
502 )
503 RETURN BOOLEAN
504 --
505 IS
506 
507   -- Table to store position_set_lines and positions for a position set.
508   l_position_set_tbl                    position_set_tbl_type ;
509   --
510   l_data_extract_id                     NUMBER ;
511   l_business_group_id                   NUMBER ;
512   --
513   l_attribute_value_id                  NUMBER ;
514   l_attribute_value                     VARCHAR2(2000) ;
515   --
516   l_first_line_sequence_id              NUMBER ;
517   l_second_set_line_index               NUMBER ;
518   l_position_set_tbl_index              NUMBER ;
519   --
520   l_position_input_tbl                  position_tbl_type ;
521   l_input_tbl_index                     NUMBER ;
522   l_position_output_tbl                 position_tbl_type ;
523   l_output_tbl_index                    NUMBER ;
524   --
525   l_position_exists_in_line_flag        VARCHAR2(1);
529   l_position_set_index                  NUMBER ;
526   l_position_exists_in_set_flag         VARCHAR2(1);
527   l_current_position_id                 NUMBER ;
528   l_current_set_line_id                 NUMBER ;
530   l_tmp_index                           NUMBER ;
531   l_count_set_line_positions            NUMBER ;
532   l_tmp_count                           NUMBER ;
533   --
534   l_last_maintained_date                DATE;
535   l_last_update_date                    DATE;
536   --
537 BEGIN
538 
539   pd('The current set ' || p_position_set_id);
540 
541 
542   -- Populate the global variable.
543   g_position_set_id := p_position_set_id;
544 
545   -- Get various information for the position set.
546   SELECT data_extract_id   ,
547 	 business_group_id
548     INTO
549 	 l_data_extract_id ,
550 	 l_business_group_id
551   FROM   psb_account_position_sets
552   WHERE  account_position_set_id = p_position_set_id ;
553 
554   --
555   -- Lock psb_account_position_sets table to prevent modifications.
556   -- Also set maintain_status to 'C' so that database trigger wont fire.
557   --
558   UPDATE psb_account_position_sets
559   SET    maintain_status = 'C'
560   WHERE  account_position_set_id = p_position_set_id ;
561 
562   --
563   -- Delete from psb_budget_positions. You must delete as everytime you run
564   -- the program, some positions may have been created, modified or deleted.
565   --
566   DELETE psb_budget_positions
567   WHERE  account_position_set_id = p_position_set_id ;
568 
569 
570   -- Reset the table.
571   l_position_set_tbl_index := 0 ;
572   l_position_set_tbl.DELETE ;
573 
574   pd('DE ' || l_data_extract_id );
575 
576   --
577   -- Get set_lines info for the given position set.
578   --
579   --
580   FOR l_set_line_rec IN
581   (
582      SELECT line_sequence_id             ,
583 	    attribute_id                 ,
584 	    attribute_value_table_flag
585      FROM   psb_acct_position_set_lines_v  lines
586      WHERE  account_position_set_id = p_position_set_id
587      ORDER  BY lines.line_sequence_id
588   )
589   LOOP
590 
591     --
592     -- Reset variable. This variable stores total number of positions in
593     -- the current set_line.
594     --
595     l_count_set_line_positions := 0 ;
596 
597     -- Check whether the attribute has been assigned values or not.
598     SELECT COUNT(*) INTO l_tmp_count
599     FROM   psb_position_set_line_values
600     WHERE  line_sequence_id = l_set_line_rec.line_sequence_id ;
601 
602     IF l_tmp_count = 0 THEN
603 
604       --
605       -- It means the attribute has not been assigned any values.  We will
606       -- consider all the positions which are not associated with the attribute.
607       -- Because it is like the positions are assigned the attribute with a
608       -- null value. ( See details in the enhancement bug#661975.)
609       --
610       pd('Set Line attribute_id : ' ||  l_set_line_rec.attribute_id) ;
611 
612       FOR l_position_rec IN
613       (
614 	 SELECT position_id
615 	 FROM   psb_positions
616 	 WHERE  data_extract_id = l_data_extract_id
617 	 MINUS
618 	 SELECT position_id
619 	 FROM   psb_position_assignments
620 	 WHERE  data_extract_id = l_data_extract_id
621 	 AND    attribute_id = l_set_line_rec.attribute_id
622       )
623       LOOP
624 
625 	pd('Pos without attr assignment ' || l_position_rec.position_id );
626 
627 	--
628 	l_count_set_line_positions := l_count_set_line_positions + 1 ;
629 	--
630 	l_position_set_tbl_index   := l_position_set_tbl_index + 1 ;
631 	--
632 	l_position_set_tbl(l_position_set_tbl_index).line_sequence_id :=
633 					    l_set_line_rec.line_sequence_id ;
634 	--
635 	l_position_set_tbl(l_position_set_tbl_index).position_id :=
636 					  l_position_rec.position_id ;
637 	--
638       END LOOP;
639       --
640 
641     ELSE
642 
643       --
644       -- The attribute has been assigned values. We will pick up positions
645       -- having the corresponding assignments.
646       --
647       FOR l_val_rec IN
648       (
649 	 SELECT attribute_value_id  ,
650 		attribute_value
651 	 FROM   psb_position_set_line_values   vals
652 	 WHERE  line_sequence_id = l_set_line_rec.line_sequence_id
653       )
654       LOOP
655 
656 	l_attribute_value_id := l_val_rec.attribute_value_id ;
657 	l_attribute_value    := l_val_rec.attribute_value    ;
658 
659 	pd('Line Val Id ' || l_val_rec.attribute_value_id );
660 	pd('Line Val    ' || l_val_rec.attribute_value )   ;
661 	pd('Att id '      || l_set_line_rec.attribute_id );
662 	pd('Line id to put in main table:' || l_set_line_rec.line_sequence_id );
663 
664 	--
665 	-- Find all the matching positions for the attribute values.
666 	-- ( Consider only base positions.)
667 	--
668 	FOR l_position_rec IN
669 	(
670 	   SELECT position_id
671 	   FROM   psb_position_assignments
672 	   WHERE  attribute_id    = l_set_line_rec.attribute_id
673 	   AND    data_extract_id = l_data_extract_id
674 	   AND    ( attribute_value_id = l_attribute_value_id
675 		    OR
679 	LOOP
676 		    attribute_value    = l_attribute_value
677 		   )
678 	)
680 
681 	  pd('Pos ' || l_position_rec.position_id );
682 
683 	  --
684 	  l_count_set_line_positions := l_count_set_line_positions + 1 ;
685 	  --
686 	  l_position_set_tbl_index   := l_position_set_tbl_index + 1 ;
687 	  --
688 	  l_position_set_tbl(l_position_set_tbl_index).line_sequence_id :=
689 					      l_set_line_rec.line_sequence_id ;
690 	  --
691 	  l_position_set_tbl(l_position_set_tbl_index).position_id :=
692 					    l_position_rec.position_id ;
693 	  --
694 	END LOOP;  /* To get matching positions for the current attribute_value
695 		    or attribute_value_id in the current set_line */
696 
697       END LOOP;  /* To get attribute values for the current set_line */
698 
699     END IF ;
700 
701     --
702     -- If attribute selection type is 'A', we select only those positions
703     -- which are present in each set line. The following condition states
704     -- the intersection of positions in all the set_line will be null.
705     --
706     IF l_count_set_line_positions = 0 AND p_attribute_selection_type = 'A'
707     THEN
708 
709       pd('Found a set_line with no positions');
710 
711       RETURN (TRUE);
712 
713     END IF ;
714 
715   END LOOP ; /* To get all the set_lines for the position set */
716 
717 
718   pd('---------------------');
719   pd('Sel Type ' || p_attribute_selection_type );
720 
721 
722   --
723   -- Process the l_position_set_tbl table as per the Attribute Selection
724   -- method defined for the set.
725   --
726 
727   IF p_attribute_selection_type = 'O' THEN
728     --
729     -- The p_attribute_selection_type 'O' means pick up all the positions
730     -- matching at least one criteria. That means take union of positions
731     -- in l_position_set_tbl table.
732     --
733     FOR i IN 1..l_position_set_tbl.COUNT
734     LOOP
735       --
736       INSERT INTO psb_budget_positions
737 		  (
738 		     account_position_set_id         ,
739 		     position_id                     ,
740 		     data_extract_id                 ,
741 		     business_group_id               ,
742 		     last_update_date                ,
743 		     last_update_login               ,
744 		     last_updated_by                 ,
745 		     created_by                      ,
746 		     creation_date
747 		  )
748 	    SELECT   g_position_set_id                   ,
749 		     l_position_set_tbl(i).position_id   ,
750 		     l_data_extract_id                   ,
751 		     l_business_group_id                 ,
752 		     g_current_date                      ,
753 		     g_current_login_id                  ,
754 		     g_current_user_id                   ,
755 		     g_current_user_id                   ,
756 		     g_current_date
757 	    FROM     dual
758 	    WHERE    NOT EXISTS
759 		     (  SELECT '1'
760 			FROM   psb_budget_positions
761 			WHERE  account_position_set_id = g_position_set_id
762 			AND    position_id             =
763 					 l_position_set_tbl(i).position_id
764 		     ) ;
765       --
766     END LOOP;
767     --
768   ELSIF p_attribute_selection_type = 'A' THEN
769     --
770     -- The p_attribute_selection_type 'A' means pick up only those positions
771     -- matching all the criteria. That means take intersection of positions
772     -- in l_position_set_tbl table with respect to a set line.
773     --
774 
775     --
776     -- Find all the positions in the first set_line.
777     --
778 
779     IF l_position_set_tbl.EXISTS(1) THEN
780       l_first_line_sequence_id := l_position_set_tbl(1).line_sequence_id ;
781     ELSE
782       -- No set lines found. No assignments can be made.
783       RETURN (TRUE) ;
784     END IF;
785 
786     -- Reset table which stores all the positions found in l_position_set_tbl.
787     l_input_tbl_index := 0 ;
788     l_position_input_tbl.DELETE  ;
789 
790     --
791     -- Finding all the positions in the very first set_line ( To implement
792     -- intersection of positions in all the set_lines. )
793     --
794     FOR i IN 1..l_position_set_tbl.COUNT
795     LOOP
796       --
797       IF l_position_set_tbl(i).line_sequence_id <> l_first_line_sequence_id
798       THEN
799 	EXIT;
800       ELSE
801 	l_input_tbl_index := l_input_tbl_index + 1 ;
802 	l_position_input_tbl(i) := l_position_set_tbl(i).position_id ;
803 
804 	pd('Line:' || l_position_set_tbl(i).line_sequence_id ||
805 	   ' Pos:' || l_position_input_tbl(i) );
806 
807       END IF ;
808       --
809     END LOOP ;
810 
811     --
812     -- Set variable which points to second line in l_position_set_tbl table.
813     -- ( It may not exists though and that check it there.
814     --
815     l_second_set_line_index := l_input_tbl_index + 1 ;
816 
817     -- Reset table which stores positions found in all the set lines.
818     l_output_tbl_index := 0 ;
819     l_position_output_tbl.DELETE  ;
820 
821     --
822     -- Process each position in l_input_tbl_index table and find whether
826     FOR i IN 1..l_position_input_tbl.COUNT
823     -- the position is present in each set_line or not. Of course we will
824     -- start from second set_line pointed to by l_position_set_index.
825     --
827     LOOP   /* To process all the position in l_position_input_tbl */
828 
829       --
830       -- Reset l_position_set_index so that it points to second set line
831       -- in l_position_set_tbl table. We do it for each position.
832       --
833       l_position_set_index := l_second_set_line_index ;
834 
835 
836       pd('Proc l_position_input_tbl Pos :' || l_position_input_tbl(i));
837 
838       -- Store the position being processed.
839       l_current_position_id := l_position_input_tbl(i) ;
840 
841       -- Flag specifies whether the current position exist in all the lines
842       -- ( hence set ) or not.
843       l_position_exists_in_set_flag := 'Y' ;
844 
845       LOOP   /* Process all the set_lines to find the current position */
846 
847 	IF l_position_set_tbl.EXISTS(l_position_set_index) THEN
848 
849 	  -- l_current_set_line_id stores the current set_line.
850 	  l_current_set_line_id :=
851 	       l_position_set_tbl(l_position_set_index).line_sequence_id;
852 
853 	  pd('Current Line :' || l_current_set_line_id );
854 
855 	  -- Flag specifies whether the current position exists in the current
856 	  -- set_line or not.
857 	  l_position_exists_in_line_flag := 'N' ;
858 
859 	  -- Process all the positions coming under the current set_line.
860 	  FOR j IN l_position_set_index..l_position_set_tbl.COUNT
861 	  LOOP
862 
863 	    IF l_position_set_tbl(j).line_sequence_id <>
864 	       l_current_set_line_id
865 	    THEN
866 	      --
867 	      -- It means we all the positions in the current set_line
868 	      -- have been processed. Update l_position_set_index and exit.
869 	      --
870 	      l_position_set_index := j + 1 ;
871 	      EXIT ;
872 	    END IF ;
873 
874 	    pd('Line:' || l_position_set_tbl(j).line_sequence_id||
875 		      ' Pos:' || l_position_set_tbl(j).position_id );
876 
877 	    IF l_position_set_tbl(j).position_id = l_current_position_id THEN
878 
879 	      -- We have found the current position in the current set_line.
880 	      l_position_exists_in_line_flag := 'Y' ;
881 
882 	      --
883 	      -- First forward l_position_set_index so that it points to the
884 	      -- next set_line and then exit the loop.
885 	      --
886 
887 	      -- Store the current value of the l_position_set_index.
888 	      l_tmp_index := j ;
889 
890 	      WHILE l_position_set_tbl.EXISTS(l_tmp_index)
891 	      LOOP
892 		--
893 		IF l_position_set_tbl(l_tmp_index).line_sequence_id <>
894 		   l_current_set_line_id
895 		THEN
896 		  EXIT ;
897 		ELSE
898 		  l_tmp_index := l_tmp_index + 1 ;
899 		END IF ;
900 		--
901 	      END LOOP; /* To forward l_position_set_index to next set_line */
902 
903 	      -- Set l_position_set_index index for l_position_set_tbl.
904 	      l_position_set_index := l_tmp_index ;
905 
906 	      -- Exit the loop now.
907 	      EXIT ;
908 
909 	    END IF ;
910 	    --
911 	  END LOOP;  /* To process positions in the current set_line */
912 
913 	  pd('line flag:' || l_position_exists_in_line_flag);
914 
915 	  --
916 	  -- If the current position is not found in the current set_line,
917 	  -- do not process rest of the lines as the current position need
918 	  -- to be there in every single set_line. Just exit the loop.
919 	  --
920 	  IF l_position_exists_in_line_flag <> 'Y' THEN
921 	    l_position_exists_in_set_flag := 'N' ;
922 	    EXIT ;
923 	  END IF ;
924 	  --
925 	ELSE
926 
927 	  -- All the set_lines have been processed, so exit.
928 	  EXIT ;
929 
930 	END IF ;  /* End of EXISTS clause for set_lines. */
931 	--
932       END LOOP ; /* To process all the set_lines for the current position */
933 
934       --
935       -- Make assignment if the current position was found in all set_lines.
936       --
937       IF l_position_exists_in_set_flag = 'Y' THEN
938 	--
939 	l_output_tbl_index := l_output_tbl_index + 1 ;
940 	l_position_output_tbl(l_output_tbl_index) := l_current_position_id ;
941 	--
942 
943 	pd('insert output tbl Pos:'||l_current_position_id);
944 
945       END IF ;
946 
947     END LOOP ;  /* To process all the position in l_position_input_tbl */
948 
949     --
950     -- Insert positions into psb_budget_positions from l_position_output_tbl.
951     --
952     FOR i in 1..l_position_output_tbl.COUNT
953     LOOP
954       --
955       INSERT INTO psb_budget_positions
956 		  (
957 		     account_position_set_id         ,
958 		     position_id                     ,
959 		     data_extract_id                 ,
960 		     business_group_id               ,
961 		     last_update_date                ,
962 		     last_update_login               ,
963 		     last_updated_by                 ,
964 		     created_by                      ,
965 		     creation_date
966 		  )
967 	    SELECT   g_position_set_id               ,
971 		     g_current_date                  ,
968 		     l_position_output_tbl(i)        ,
969 		     l_data_extract_id               ,
970 		     l_business_group_id             ,
972 		     g_current_login_id              ,
973 		     g_current_user_id               ,
974 		     g_current_user_id               ,
975 		     g_current_date
976 	    FROM     dual
977 	    WHERE    NOT EXISTS
978 		     (  SELECT '1'
979 			FROM   psb_budget_positions
980 			WHERE  account_position_set_id = g_position_set_id
981 			AND    position_id             =
982 						   l_position_output_tbl(i)
983 		     ) ;
984       --
985     END LOOP;
986     --
987   END IF;  /* End of p_attribute_selection_type clause */
988 
989   --
990   -- Update last_maintained_date column. Set maintain_status to 'C'
991   -- ( meaning updated from PSBVMBAB module) so now the database trigger
992   -- will not fire.
993   --
994   UPDATE psb_account_position_sets
995   SET    maintain_status         = 'C' ,
996 	 last_maintained_date    = g_current_date
997   WHERE  account_position_set_id = p_position_set_id;
998   --
999   RETURN (TRUE);
1000 
1001 EXCEPTION
1002   WHEN OTHERS THEN
1003     --
1004     IF FND_MSG_PUB.Check_Msg_Level ( FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR ) THEN
1005       FND_MSG_PUB.Add_Exc_Msg (  G_PKG_NAME,
1006 				 'Populate_Budget_Position_Set' );
1007     END if;
1008     --
1009     RETURN (FALSE);
1010     --
1011 END Populate_Budget_Position_Set ;
1012 /*---------------------------------------------------------------------------*/
1013 
1014 
1015 
1016 /*===========================================================================+
1017  |                   PROCEDURE Populate_Budget_Positions_CP                  |
1018  +===========================================================================*/
1019 --
1020 -- This is the execution file for the concurrent program 'Maintain Budget
1021 -- Account Codes'.
1022 --
1023 PROCEDURE Populate_Budget_Positions_CP
1024 (
1025   errbuf                      OUT  NOCOPY      VARCHAR2  ,
1026   retcode                     OUT  NOCOPY      VARCHAR2  ,
1027   --
1028   p_data_extract_id           IN       NUMBER   := FND_API.G_MISS_NUM ,
1029   p_position_set_id           IN       NUMBER   := FND_API.G_MISS_NUM
1030 )
1031 IS
1032   --
1033   l_api_name       CONSTANT VARCHAR2(30)   := 'Populate_Budget_Positions_CP' ;
1034   l_api_version    CONSTANT NUMBER         :=  1.0 ;
1035   --
1036   l_return_status           VARCHAR2(1) ;
1037   l_msg_count               NUMBER ;
1038   l_msg_data                VARCHAR2(2000) ;
1039   --
1040 BEGIN
1041   --
1042   SAVEPOINT Populate_Budget_Pos_CP_Pvt ;
1043   --
1044   IF ( p_data_extract_id = FND_API.G_MISS_NUM OR p_data_extract_id IS NULL )
1045   THEN
1046     FND_FILE.Put_Line( FND_FILE.OUTPUT, 'Processing all the position sets.');
1047   ELSE
1048     --
1049     IF ( p_position_set_id = FND_API.G_MISS_NUM OR p_position_set_id IS NULL )
1050     THEN
1051       --
1052       FND_FILE.Put_Line( FND_FILE.OUTPUT,
1053 			 'Processing position sets for data extract id : ' ||
1054 			 p_data_extract_id );
1055       --
1056     ELSE
1057       --
1058       FND_FILE.Put_Line( FND_FILE.OUTPUT,
1059 			 'Processing the given position set id : ' ||
1060 			 p_position_set_id );
1061       --
1062     END IF;
1063     --
1064   END IF;
1065 
1066   --
1067   PSB_Budget_Position_Pvt.Populate_Budget_Positions
1068   (
1069      p_api_version       =>  1.0                         ,
1070      p_init_msg_list     =>  FND_API.G_TRUE              ,
1071      p_commit            =>  FND_API.G_FALSE             ,
1072      p_validation_level  =>  FND_API.G_VALID_LEVEL_FULL  ,
1073      p_return_status     =>  l_return_status             ,
1074      p_msg_count         =>  l_msg_count                 ,
1075      p_msg_data          =>  l_msg_data                  ,
1076      p_data_extract_id   =>  p_data_extract_id           ,
1077      p_position_set_id   =>  p_position_set_id
1078   );
1079 
1080   --
1081   IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
1082     RAISE FND_API.G_EXC_ERROR;
1083   END IF;
1084   --
1085 
1086   --
1087     /* Start Bug No. 2322856 */
1088 --  PSB_MESSAGE_S.Print_Success ;
1089     /* End Bug No. 2322856 */
1090   retcode := 0 ;
1091   --
1092   COMMIT WORK;
1093   --
1094 EXCEPTION
1095   --
1096   WHEN FND_API.G_EXC_ERROR THEN
1097     --
1098     ROLLBACK TO Populate_Budget_Pos_CP_Pvt ;
1099     PSB_MESSAGE_S.Print_Error ( p_mode         => FND_FILE.LOG ,
1100 				p_print_header =>  FND_API.G_TRUE ) ;
1101     retcode := 2 ;
1102     --
1103   WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
1104     --
1105     ROLLBACK TO Populate_Budget_Pos_CP_Pvt ;
1106     PSB_MESSAGE_S.Print_Error ( p_mode         => FND_FILE.LOG ,
1107 				p_print_header =>  FND_API.G_TRUE ) ;
1108     retcode := 2 ;
1109     --
1110   WHEN OTHERS THEN
1111     --
1112     ROLLBACK TO Populate_Budget_Pos_CP_Pvt ;
1113     IF FND_MSG_PUB.Check_Msg_Level( FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR ) THEN
1114       --
1115       FND_MSG_PUB.Add_Exc_Msg( G_PKG_NAME ,
1116 			       l_api_name  ) ;
1117     END IF ;
1118     --
1119     PSB_MESSAGE_S.Print_Error ( p_mode         =>  FND_FILE.LOG ,
1120 				p_print_header =>  FND_API.G_TRUE ) ;
1121     retcode := 2 ;
1122     --
1123 END Populate_Budget_Positions_CP ;
1124 /*---------------------------------------------------------------------------*/
1125 
1126 
1127 
1128 /*===========================================================================+
1129  |                     PROCEDURE pd (Private)                                |
1130  +===========================================================================*/
1131 --
1132 -- Private procedure to print debug info. The name is tried to keep as
1133 -- short as possible for better documentaion.
1134 --
1135 PROCEDURE pd
1136 (
1137    p_message                   IN   VARCHAR2
1138 )
1139 IS
1140 --
1141 BEGIN
1142 
1143   IF g_debug_flag = 'Y' THEN
1144     NULL;
1145     -- dbms_output.put_line(p_message) ;
1146   END IF;
1147 
1148 END pd ;
1149 /*---------------------------------------------------------------------------*/
1150 
1151 
1152 END PSB_Budget_Position_Pvt;