DBA Data[Home] [Help]

PACKAGE BODY: APPS.PA_SECURITY

Source


1 PACKAGE BODY pa_security AS
2 /* $Header: PAPLSECB.pls 120.1.12010000.3 2009/06/08 12:00:28 paljain ship $ */
3 
4 
5    /* ----------------------------------------------------------------------
6    ||
7    ||  Function Name:  Initialize
8    ||
9    ||  Input Parameters:
10    ||     X_user_id     <-- identifier of the application user
11    ||	  X_calling_module  <-- hard-coded string that refers to the
12    ||                           module that is calling pa_security
13    ||				functions
14    ||
15    ||  Description:
16    ||     This function is called to initialize package globals that are
17    ||     referenced by the security functions.  Each form that uses
18    ||     views that are secured MUST execute this procedure during form
19    ||     startup, otherwise the logic in the security functions built into
20    ||     secured views is not executed, and the views return all rows.
21    ||
22    ||     This built-in default (return unsecured data if package globals
23    ||     are not enabled) enables system administrators using SQL*Plus to
24    ||     query data to have access all data.
25    ||
26    ||     In order to secure data in external applications or custom
27    ||     modules that are not part of core PA code, this procedure must
28    ||     be called before querying secured views.
29    ||
30    || ---------------------------------------------------------------------
31    */
32 
33   PROCEDURE Initialize ( X_user_id         IN NUMBER
34                        , X_calling_module  IN VARCHAR2 )
35   IS
36   v_resp_id      NUMBER;
37   v_resp_appl_id NUMBER;
38   BEGIN
39 
40     IF ( X_user_id  IS NOT NULL ) THEN
41       G_user_id := X_user_id;
42       G_person_id := pa_utils.GetEmpIdFromUser( G_user_id );
43     ELSE
44       G_person_id := NULL;
45     END IF;
46 
47     v_resp_id := fnd_global.resp_id;
48     v_resp_appl_id := fnd_global.resp_appl_id;
49 
50     IF fnd_profile.value_specific('PA_SUPER_PROJECT',x_user_id, v_resp_id, v_resp_appl_id) = 'Y' THEN
51       G_cross_project_user := 'Y';
52     ELSE
53       G_cross_project_user := 'N';
54     END IF;
55 
56     IF fnd_profile.value_specific('PA_SUPER_PROJECT_VIEW',x_user_id, v_resp_id, v_resp_appl_id) = 'Y' THEN
57       G_cross_project_view := 'Y';
58     ELSE
59       G_cross_project_view := 'N';
60     END IF;
61 
62     G_module_name := X_calling_module;
63 
64     IF ( G_module_name = 'PAXTRAPE.CROSS-PROJECT' ) THEN
65       G_query_allowed := 'Y';
66       G_update_allowed := 'Y';
67       G_view_labor_costs := 'Y';
68     ELSE
69       G_view_labor_costs := NULL;
70       G_query_allowed := NULL;
71       G_update_allowed := NULL;
72     END IF;
73 
74   END Initialize;
75 
76 
77 
78    /* ----------------------------------------------------------------------
79    ||
80    ||  Function Name:  allow_query
81    ||
82    ||  Input Parameters:
83    ||     X_project_id     <-- project identifier
84    ||
85    ||  Description:
86    ||     This function determines whether a user has query access to a
87    ||     particular project.
88    ||
89    ||     The function first checks if the package variable G_query_allowed
90    ||     has been initiated with a value.  This global variable is set
91    ||     during the Initialize procedure and is used to override normal
92    ||     validation in the allow_query function (this enables users who
93    ||     connect to the database in custom modules or in SQL*Plus to
94    ||     access all data in secured views without enforcing project-based
95    ||     security).
96    ||
97    ||     If the global variable is not set, then this function calls the
98    ||     client extension API to determine whether or not the user has
99    ||     query privileges for the given project.
100    ||
101    ||     The default validation that PA seeds in the client extension for
102    ||     'ALLOW_QUERY' is to verify that the user has cross project view/update
103    ||     access, or has the project authority role in the organizational domain
104    ||     of this project, or is a key member of the project.
105    ||
106    ||     There are only two valid values returned from the extension
107    ||     procedure:  'Y' or 'N'.  If the value returned is not one of
108    ||     these values, then this function returns 'Y'.
109    ||     -- changed the return value to 'N' for bug 2635016
110    ||
114   FUNCTION allow_query ( X_project_id     IN NUMBER) RETURN VARCHAR2
111    || ---------------------------------------------------------------------
112    */
113 
115   IS
116     V_allow_query               VARCHAR2(1);
117     V_allow_update              VARCHAR2(1); /* added for bug 2686117 */
118 
119   BEGIN
120 
121     /*
122      * Bug# 918652
123      */
124     IF  ( G_module_name IS NULL ) THEN
125       RETURN('Y');
126     END IF;
127 
128 /* Bug 2686117 Start */
129     IF ( G_update_allowed = 'Y') THEN
130       RETURN( G_update_allowed );
131     END IF;
132 
133     pa_security_extn.check_project_access(
134                           X_project_id
135                         , G_person_id
136                         , G_cross_project_user
137                         , G_module_name
138                         , 'ALLOW_UPDATE'
139                         , V_allow_update );
140 
141     IF ( V_allow_update = 'Y') THEN
142       RETURN( V_allow_update );
143 /* Bug 2686117 End */
144 
145     ELSE
146 
147         IF ( G_query_allowed IS NOT NULL ) THEN
148           RETURN( G_query_allowed );
149         END IF;
150 
151         pa_security_extn.check_project_access(
152                               X_project_id
153                             , G_person_id
154                             , G_cross_project_user
155                         , G_module_name
156                         , 'ALLOW_QUERY'
157                         , V_allow_query
158                         , G_cross_project_view );
159 
160         IF ( V_allow_query IN ('Y', 'N') ) THEN
161           RETURN( V_allow_query );
162         ELSE
163 /* changed the return value from 'Y' to N for bug 2635016 */
164           RETURN( 'N' );
165         END IF;
166     END IF;
167   END allow_query;
168 
169 
170 
171 
172    /* ----------------------------------------------------------------------
173    ||
174    ||  Function Name:  allow_update
175    ||
176    ||  Input Parameters:
177    ||     X_project_id     <-- project identifier
178    ||
179    ||  Description:
180    ||     This function determines whether a user has update privileges for
181    ||     a particular project.
182    ||
183    ||     The structure is identical to the allow_query function. The default
184    ||     validation that PA seeds in the client extension for 'ALLOW_QUERY' is
185    ||     to verify that the user has cross project update access, or has the
186    ||     project authority role in the organizational domain of this project,
187    ||     or is a key member of the project.
188    ||
189    || ---------------------------------------------------------------------
190    */
191 
192   FUNCTION allow_update ( X_project_id     IN NUMBER) RETURN VARCHAR2
193   IS
194     V_allow_update  		VARCHAR2(1);
195 
196   BEGIN
197 
198     /*
199      * Bug# 918652
200      */
201     IF  ( G_module_name IS NULL ) THEN
202       RETURN('Y');
203     END IF;
204 
205     IF ( G_update_allowed IS NOT NULL ) THEN
206       RETURN( G_update_allowed );
207     END IF;
208 
209     pa_security_extn.check_project_access(
210                           X_project_id
211                         , G_person_id
212                         , G_cross_project_user
213                         , G_module_name
214                         , 'ALLOW_UPDATE'
215                         , V_allow_update );
216 
217     IF ( V_allow_update IN ('Y', 'N') ) THEN
218       RETURN( V_allow_update );
219     ELSE
220 /* changed the return value from 'Y' to 'N' for bug 2635016 */
221       RETURN( 'N' );
222     END IF;
223 
224   END allow_update;
225 
226 
227 
228    /* ----------------------------------------------------------------------
229    ||
230    ||  Function Name:  view_labor_costs
231    ||
232    ||  Input Parameters:
233    ||     X_project_id     <-- project identifier
234    ||
235    ||  Description:
236    ||     This function determines whether or not labor cost amounts are
237    ||     displayed when the user queries detail project expenditure items.
238    ||
239    ||     The structure of the function is identical to the allow_query
240    ||     function.  The default validation that PA seeds in the client
241    ||     extension for 'VIEW_LABOR_COSTS' is to verify that the user
242    ||     is a valid key member for the project and that his/her project
243    ||     role type of this assignment is defined with Query Labor Cost
244    ||     privilege.
245    ||
246    || ---------------------------------------------------------------------
247    */
248 
249   FUNCTION view_labor_costs ( X_project_id      IN NUMBER) RETURN VARCHAR2
250   IS
251     V_view_labor_costs          VARCHAR2(1);
252 
253   BEGIN
254 
255     /*
256      * Bug# 918652
257      */
258     IF  ( G_module_name IS NULL ) THEN
259       RETURN('Y');
260     END IF;
261 
262     IF ( G_view_labor_costs IS NOT NULL ) THEN
263       RETURN( G_view_labor_costs );
264     END IF;
265 
266     pa_security_extn.check_project_access(
267                           X_project_id
268                         , G_person_id
269                         , G_cross_project_user
270                         , G_module_name
271                         , 'VIEW_LABOR_COSTS'
272                         , V_view_labor_costs );
273 
277       RETURN( 'Y' );
274     IF ( V_view_labor_costs IN ('N', 'Y') ) THEN
275       RETURN( V_view_labor_costs );
276     ELSE
278     END IF;
279 
280   END view_labor_costs;
281 
282       /* ----------------------------------------------------------------------
283  	    ||
284  	    ||  Function Name:  view_labor_costs_new
285  	    ||
286  	    ||  Input Parameters:
287  	    ||     X_project_id     <-- project identifier
288  	    ||
289  	    ||  Description:
290  	    ||     This function determines whether or not labor cost amounts are
291  	    ||     displayed when the user queries detail project expenditure items.
292  	    ||     Caching logic is implemented for performance
293  	    ||
294  	    ||     The structure of the function is identical to the allow_query
295  	    ||     function.  The default validation that PA seeds in the client
296  	    ||     extension for 'VIEW_LABOR_COSTS' is to verify that the user
297  	    ||     is a valid key member for the project and that his/her project
298  	    ||     role type of this assignment is defined with Query Labor Cost
299  	    ||     privilege.
300  	    ||
301  	    ||     15-01-2009 anuragar  Added this for caching purpose so that
302  	    ||                          performance doesnt take a hit for bug7192736
303  	    ||
304  	    || ---------------------------------------------------------------------
305  	    */
306 
307  	   FUNCTION view_labor_costs_new ( X_project_id      IN NUMBER) RETURN NUMBER
308  	   IS
309  	     V_view_labor_costs          VARCHAR2(1);
310 
311  	   BEGIN
312 
313  	   --For bug 7192736
314  	   Initialize (fnd_global.user_id, 'RESOURCE_SUMMARY') ;
315 
316  	           G_proj_id := X_project_id;
317  	           V_view_labor_costs := view_labor_costs(X_project_id);
318  	           if(V_view_labor_costs = 'Y')
319  	             then G_allow_result := 1;
320  	           else
321  	                  G_allow_result := NULL;
322  	           end if;
323  	                 return G_allow_result;
324 
325  	   END view_labor_costs_new;
326 
327             /* ----------------------------------------------------------------------
328    	    ||
329  	    ||  Function Name:  view_labor_costs_new2
330  	    ||
331  	    ||  Input Parameters:
332  	    ||     X_project_id     <-- project identifier
333  	    ||
334  	    ||  Description:
335  	    ||     This function determines whether or not labor cost amounts are
336  	    ||     displayed when the user queries detail project expenditure items.
337  	    ||     This is used from Task Summary Drilldown pages.
338  	    ||
339  	    ||     The structure of the function is identical to the allow_query
340  	    ||     function.  The default validation that PA seeds in the client
341  	    ||     extension for 'VIEW_LABOR_COSTS' is to verify that the user
342  	    ||     is a valid key member for the project and that his/her project
343  	    ||     role type of this assignment is defined with Query Labor Cost
344  	    ||     privilege.
345  	    ||
346  	    ||     23-04-2009  paljain   Adding this function for Bug fix 8460451.
347  	    ||                           Please check the bug for more details.
348  	    || ---------------------------------------------------------------------
349  	    */
350  	 FUNCTION view_labor_costs_new2 ( X_project_id      IN NUMBER) RETURN VARCHAR2
351  	   IS
352  	     V_view_labor_costs          VARCHAR2(1);
353  	     x_return_status         VARCHAR2(1);
354  	   BEGIN
355  	   Initialize (fnd_global.user_id, 'TASK_SUMMARY') ;
356 
357  	           G_proj_id := X_project_id;
358  	           V_view_labor_costs := view_labor_costs(X_project_id);
359  	           if(V_view_labor_costs = 'Y')
360  	             then x_return_status := 'T';
361  	           else
362  	                  x_return_status := 'F';
363  	           end if;
364  	                 return x_return_status;
365 
366  	   END view_labor_costs_new2;
367 
368    /* ----------------------------------------------------------------------
369    ||
370    ||  Procedure Name:  set_value
371    ||
372    ||  Input Parameters:
373    ||     X_security_level     <-- Hard-Coded value to specify which
374    ||                              level of security to set global values
375    ||     X_value              <-- The value to assign to the package
376    ||                              global.  Once set, this package global
377    ||                              is returned when the security function
378    ||                              for that level is called instead of
379    ||                              executing the function validation code.
380    ||
381    ||  Description:
382    ||     This procedure is called to assign to a given value to the
383    ||     security package global variable specified.  It is used in
384    ||     forms that drilldown to details for a specific project so that
385    ||     security validation is only executed once.
386    ||
387    ||     For example, labor cost security is implemented by embedding the
388    ||     view_labor_costs function in the view definition that displays
389    ||     expenditure item details for a project.  Since the function is
390    ||     row dependent (ie, based on project and expenditure type), it is
391    ||     executed for each record queried.  Since the Expenditure Inquiry
392    ||     form (PROJECT mode) queries expenditure items for a
393    ||     specific project, the logic in the view_labor_costs function
394    ||     needs to be executed only once.  Therefore, the package global
395    ||     variable for view labor cost security is initialized when
396    ||     the project number/name specified in the form is validated.  When
400    || ---------------------------------------------------------------------
397    ||     expenditure items are queried, the security function returns
398    ||     the global value instead of executing its validation logic.
399    ||
401    */
402 
403   PROCEDURE set_value ( X_security_level  IN VARCHAR2
404                       , X_value           IN VARCHAR2 )
405   IS
406   BEGIN
407 
408     IF ( X_security_level = 'VIEW_LABOR_COSTS' ) THEN
409       IF ( X_value IS NULL ) THEN
410         G_view_labor_costs := NULL;
411       ELSE
412         G_view_labor_costs := X_value;
413       END IF;
414     ELSIF ( X_security_level = 'ALLOW_UPDATE' ) THEN
415       IF ( X_value IS NULL ) THEN
416         G_update_allowed := NULL;
417       ELSE
418         G_update_allowed := X_value;
419       END IF;
420     ELSIF ( X_security_level = 'ALLOW_QUERY' ) THEN
421       IF ( X_value IS NULL ) THEN
422         G_query_allowed := NULL;
423       ELSE
424         G_query_allowed := X_value;
425       END IF;
426     END IF;
427 
428   END set_value;
429 
430 
431 
432   /* ----------------------------------------------------------------------
433    ||
434    ||  Function Name:  check_key_member
435    ||
436    ||  Input Parameters:
437    ||     X_person_id     <-- Identifier of the person
438    ||     X_project_id    <-- Identifier of the project
439    ||
440    ||  Return value:
441    ||     Y  <-- Indicates that the person specified is an active key
442    ||            member for the project specified as of the current date
443    ||     N  <-- The person is not an active key member for the project
444    ||     NULL <-- Return value if either input parameter is not given
445    ||
446    || ---------------------------------------------------------------------
447    */
448 
449   FUNCTION check_key_member ( X_person_id   IN NUMBER
450                             , X_project_id  IN NUMBER ) RETURN VARCHAR2
451   IS
452     dummy    NUMBER;
453 
454   BEGIN
455     IF ( X_person_id IS NULL OR X_project_id IS NULL ) THEN
456       RETURN( NULL );
457     END IF;
458 
459     BEGIN
460            SELECT 1
461              INTO dummy
462              FROM pa_project_players
463             WHERE project_id = X_project_id
464               AND person_id = X_person_id
465 	AND TRUNC(sysdate) >= trunc(start_date_active)
466 	AND TRUNC(sysdate) <= trunc(NVL(end_date_active, sysdate+1));
467        RETURN( 'Y' );
468 
469     EXCEPTION
470       WHEN  NO_DATA_FOUND  THEN
471         RETURN( 'N' );
472      WHEN  TOO_MANY_ROWS   THEN
473         RETURN ('Y');
474      WHEN OTHERS THEN
475         RETURN ('N');
476 
477     END;
478 
479   END check_key_member;
480 
481 
482 
483   /* ----------------------------------------------------------------------
484    ||
485    ||  Function Name:  check_labor_cost_access
486    ||
487    ||  Input Parameters:
488    ||     X_person_id     <-- Identifier of the person
489    ||     X_project_id    <-- Identifier of the project
490    ||
491    ||  Return value:
492    ||     Y  <-- Indicates that the person specified is a key member
493    ||            with a project role type that allows query of labor costs
494    ||            for the specified project
495    ||     N  <-- The person is not an active key member for the project or
496    ||            is an active key member but with a project role type that
497    ||            does not permit query of labor cost amounts
498    ||     NULL <-- Return value if either input parameter is not given
499    ||
500    || ---------------------------------------------------------------------
501    */
502 
503   FUNCTION check_labor_cost_access ( X_person_id  IN NUMBER
504                                    , X_project_id  IN NUMBER )
505        RETURN VARCHAR2
506   IS
507     dummy     NUMBER;
508   BEGIN
509     IF ( X_person_id IS NULL  OR  X_project_id IS NULL ) THEN
510       RETURN( NULL );
511     END IF;
512 
513     BEGIN
514            SELECT 1
515              INTO dummy
516              --FROM pa_project_role_types rt --bug 4004821
517              FROM pa_project_role_types_b rt
518            ,      pa_project_players pp
519 	   ,      pa_role_controls rc    -- Added for bug 3058844
520             WHERE rt.project_role_type = pp.project_role_type
521 	     /*  Below code added for  bug 3058844 */
522 	      AND rt.project_role_id = rc.project_role_id
523 	      AND rc.role_control_code = 'ALLOW_QUERY_LABOR_COST'
524 	     /* Code addition ends for bug 3058844 */
525   	      AND TRUNC(sysdate) >= trunc(pp.start_date_active)
526 	      AND TRUNC(sysdate) <= trunc(NVL(pp.end_date_active, sysdate+1))
527               AND pp.person_id = X_person_id
528               AND pp.project_id = X_project_id;
529 
530       RETURN( 'Y' );
531 
532     EXCEPTION
533       WHEN  NO_DATA_FOUND  THEN
534         RETURN( 'N' );
535      WHEN  TOO_MANY_ROWS   THEN
536         RETURN ('Y');
537      WHEN OTHERS THEN
538         RETURN ('N');
539 
540     END;
541 
542   END check_labor_cost_access;
543 
544 
545  /* ----------------------------------------------------------------------
546    ||
547    ||  Function Name:  check_project_authority
548    ||
549    ||  Input Parameters:
550    ||     X_person_id     <-- Identifier of the person
551    ||     X_project_id    <-- Identifier of the project
552    ||
556    ||     N  <-- The person is not a project authority, or is a project authority
553    ||  Return value:
554    ||     Y  <-- Indicates that the person specified has the project authority
555    ||            role that permits access to the specified project
557    ||            for an organization that does not encompass the specified project
558    ||     NULL <-- Return value if either input parameter is not given
559    ||
560    || ---------------------------------------------------------------------
561    */
562 
563 FUNCTION check_project_authority ( X_person_id  IN NUMBER,
564                                    X_project_id IN NUMBER ) RETURN VARCHAR2
565   IS
566     CURSOR c1 IS
567        SELECT '1'
568        FROM pa_projects_all ppa,
569             pa_project_role_types_b ppr, -- Added for bug 3224170
570             fnd_grants fg,
571             fnd_objects fo
572        WHERE
573             --fg.grantee_key = 'PER:'||X_person_id and  /* commenting this line for 11.5.10 security changes */
574             fg.grantee_key = PA_SECURITY_PVT.get_grantee_key( 'PERSON', X_person_id, 'N') and
575 /* replaced the above line with this call. The last paramater will assert that the function will not write to database. */
576             fg.grantee_type = 'USER' and
577 												fg.menu_id = ppr.menu_id  and  -- Added for bug 3224170
578 												ppr.project_role_id = 3  and   -- Added for bug 3224170
579             ppa.project_id = X_project_id and
580             to_char(ppa.carrying_out_organization_id) = fg.instance_pk1_value and  -- bug 2777621
581             fg.object_id = fo.object_id and
582             fo.obj_name = 'ORGANIZATION' and
583             fg.instance_type = 'INSTANCE' and
584             TRUNC(sysdate) >= trunc(fg.start_date) and
585   	    trunc(sysdate) <= trunc(NVL(fg.end_date, sysdate+1));
586 
587     v_dummy VARCHAR2(1);
588   BEGIN
589     IF( X_person_id IS NULL or X_project_id IS NULL ) THEN
590        RETURN( NULL );
591     END IF;
592 
593     open c1;
594     fetch c1 into v_dummy;
595     IF c1%notfound THEN
596       close c1;
597       RETURN( 'N' );
598     ELSE
599       close c1;
600       RETURN( 'Y' );
601     END IF;
602   EXCEPTION
603     WHEN OTHERS THEN
604       RETURN( 'N' );
605   END check_project_authority;
606 
607   /* ----------------------------------------------------------------------
608    ||
609    ||  Function Name:  check_key_member_no_dates
610    ||
611    ||  Input Parameters:
612    ||     X_person_id     <-- Identifier of the person
613    ||     X_project_id    <-- Identifier of the project
614    ||
615    ||  Return value:
616    ||     Y  <-- Indicates that the person specified is a
617    ||            member for the project.
618    ||     N  <-- The person is not a member for the project.
619    ||     NULL <-- Return value if either input parameter is not given
620    ||
621    || ---------------------------------------------------------------------
622    */
623 
624   FUNCTION check_key_member_no_dates ( X_person_id   IN NUMBER
625                             , X_project_id  IN NUMBER ) RETURN VARCHAR2
626   IS
627     dummy    NUMBER;
628 
629   BEGIN
630     IF ( X_person_id IS NULL OR X_project_id IS NULL ) THEN
631       RETURN( NULL );
632     END IF;
633 
634     BEGIN
635            SELECT 1
636              INTO dummy
637              FROM pa_project_players
638             WHERE project_id = X_project_id
639               AND person_id = X_person_id;
640 
641    RETURN( 'Y' );
642 
643     EXCEPTION
644       WHEN  NO_DATA_FOUND  THEN
645         RETURN( 'N' );
646      WHEN  TOO_MANY_ROWS   THEN
647         RETURN ('Y');
648      WHEN OTHERS THEN
649         RETURN ('N');
650     END;
651 
652   END check_key_member_no_dates;
653 
654  /* ----------------------------------------------------------------------
655    ||
656    ||  Function Name:  check_forecast_authority
657    ||
658    ||  Input Parameters:
659    ||     p_person_id     <-- Identifier of the person
660    ||     p_project_id    <-- Identifier of the project
661    ||
662    ||  Return value:
663    ||     Y  <-- Indicates that the person specified has the forecast authority
664    ||            role that permits access to the specified project
665    ||     N  <-- The person is not a forecast authority
666    ||     NULL <-- Return value if either input parameter is not given
667    ||
668    || ---------------------------------------------------------------------
669    */
670 
671 /*Enhancement 6519194 - commenting out this function*/
672 /*FUNCTION check_forecast_authority ( X_person_id  IN NUMBER,
673                                     X_project_id IN NUMBER ) RETURN VARCHAR2
674   IS
675     CURSOR c1 IS
676        SELECT '1'
677        FROM pa_projects_all ppa,
678             fnd_grants fg,
679             fnd_objects fo,
680             fnd_menus fm
681        WHERE */
682             --fg.grantee_key = 'PER:'||X_person_id and  /* commenting this line for 11.5.10 security changes */
683  /*           fg.grantee_key = PA_SECURITY_PVT.get_grantee_key( 'PERSON', X_person_id, 'N') and*/
684 /* replaced the above line with this call. The last paramater will assert that the function will not write to database. */
685 /*            fg.grantee_type = 'USER' and
686             ppa.project_id = X_project_id and
687             to_char(ppa.carrying_out_organization_id) = fg.instance_pk1_value and  -- bug2777621
688             fg.object_id = fo.object_id and
689             fm.menu_name  = 'PA_PRM_FCST_AUTH'  and
690             fg.menu_id = fm.menu_id and
691             fo.obj_name = 'ORGANIZATION' and
692             fg.instance_type = 'INSTANCE' and
693             TRUNC(sysdate) >= trunc(fg.start_date) and
694             trunc(sysdate) <= trunc(NVL(fg.end_date, sysdate+1));
695 
696     v_dummy VARCHAR2(1);
697   BEGIN
698 
699     IF( X_person_id IS NULL or X_project_id IS NULL ) THEN
700        RETURN( NULL );
701     END IF;
702 
703     open c1;
704     fetch c1 into v_dummy;
705     IF c1%notfound THEN
706       close c1;
707       RETURN( 'N' );
708     ELSE
709       close c1;
710       RETURN( 'Y' );
711     END IF;
712 
713   EXCEPTION
714     WHEN OTHERS THEN
715       RETURN( 'N' );
716 
717 END check_forecast_authority;
718 */
719 END pa_security;