DBA Data[Home] [Help]

PACKAGE BODY: APPS.MO_GLOBAL

Source


1 PACKAGE BODY mo_global AS
2 /* $Header: AFMOGBLB.pls 120.37.12010000.2 2008/10/29 19:54:56 shnaraya ship $ */
3 
4   g_multi_org_flag fnd_product_groups.multi_org_flag%TYPE;
5   g_access_mode       varchar2(1);
6   g_current_org_id    number(15);
7   g_ou_count          PLS_INTEGER;
8   g_sync              varchar2(1);
9   g_init_access_mode varchar2(1);
10   g_ou_id_tab OrgIdTab;
11 
12   g_old_sp_id fnd_profile_option_values.profile_option_value%TYPE := NULL;
13   g_old_org_id fnd_profile_option_values.profile_option_value%TYPE := NULL;
14   g_old_user_id NUMBER;
15   g_old_resp_id NUMBER;
16 
17   TYPE ApplShortNameTab is TABLE OF fnd_mo_product_init.application_short_name%TYPE
18   INDEX BY BINARY_INTEGER;
19   TYPE StatusTab is TABLE OF fnd_mo_product_init.status%TYPE
20   INDEX BY BINARY_INTEGER;
21 
22 --
23 -- Private functions and procedures
24 --
25 PROCEDURE generic_error(routine in varchar2,
26 			errcode in number,
27 			errmsg in varchar2) IS
28 BEGIN
29    fnd_message.set_name('FND', 'SQL_PLSQL_ERROR');
30    fnd_message.set_token('ROUTINE', routine);
31    fnd_message.set_token('ERRNO', errcode);
32    fnd_message.set_token('REASON', errmsg);
33    IF (FND_LOG.LEVEL_UNEXPECTED >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
34       FND_LOG.MESSAGE(FND_LOG.LEVEL_UNEXPECTED, routine, FALSE);
35    END IF;
36    fnd_message.raise_error;
37 END;
38 
39 --
40 --   This is an internal API that accepts the ORG_ID, SECURITY_PROFILE_ID
41 --   and populates the Multi-Org temporary table based on the access
42 --   enabled status of the product. The API returns the current org for
43 --   single access mode and view all flag for all access mode.
44 --
45 --   Product teams should never access the temporary table directly
46 --   because it may become obsolete in the future.
47 --   The contents of the temporary table can be accessed by the
48 --   APIs provided within this package and the MO_UTILS package.
49 
50 PROCEDURE populate_orgs (p_org_id_char     IN         VARCHAR2,
51                          p_sp_id_char      IN         VARCHAR2,
52                          p_current_org_id  OUT NOCOPY VARCHAR2,
53                          p_view_all_org    OUT NOCOPY VARCHAR2)
54 IS
55 
56   t_org_id                 OrgidTab;
57   t_ou_name                OuNameTab;
58   t_common_org_id          OrgidTab;
59   t_common_ou_name         OuNameTab;
60   t_pref_org_id            OrgidTab;
61   t_delete_org_id          OrgidTab;
62   sync_ind                 VARCHAR2(1) := 'N';
63   match_ind                VARCHAR2(1);
64   k                        BINARY_INTEGER := 1;
65   l                        BINARY_INTEGER := 1;
66 
67   is_view_all_org          VARCHAR2(1);
68   l_sp_name                per_security_profiles.security_profile_name%TYPE;
69   l_bg_id                  per_security_profiles.business_group_id%TYPE;
70 
71 
72   CURSOR c1 IS
73     SELECT per.organization_id  organization_id
74          , hr.NAME              name
75       FROM per_organization_list per
76          , hr_operating_units hr
77      WHERE per.security_profile_id = to_number(p_sp_id_char)
78        AND hr.organization_id = per.organization_id
79        AND hr.usable_flag is null;
80 
81   CURSOR c2 IS
82     SELECT hr.organization_id  organization_id
83          , hr.name              name
84       FROM hr_operating_units hr
85      WHERE hr.organization_id = to_number(p_org_id_char)
86        AND hr.usable_flag is null;
87 
88   -- Added the following cursor to support view all security profile with a
89   -- business group (BG). For a view all security profile within a BG, the
90   -- per_organization_list is not populated, so should directly get the
91   -- operating units for the particular business group from hr_operating_units
92   -- view.
93 
94   -- Commented out the reference of the business group name in the WHERE
95   -- Clause, since the SQL is supposed to return all operating units under
96   -- the business group  (Bug 2720910)
97 
98   CURSOR c3 (X_sp_name VARCHAR2,
99              X_bg_id   NUMBER) IS
100     SELECT hr.organization_id  organization_id
101          , hr.name              name
102       FROM hr_operating_units hr
103      WHERE hr.business_group_id = X_bg_id
104        AND hr.usable_flag is null;
105 
106   -- Added the following cursor to support global view all security profile
107   -- For a global view all security profile, the per_organization_list is
108   -- not populated, so should directly get all operating units from
109   -- hr_operating_units view.
110 
111   CURSOR c4 IS
112     SELECT hr.organization_id  organization_id
113          , hr.name              name
114       FROM hr_operating_units hr
115      WHERE hr.usable_flag is null;
116 
117   -- Added the following cursor to support synchronization with the multi-org
118   -- preference setup.
119 
120   CURSOR c5 IS
121     SELECT organization_id
122       FROM fnd_mo_sp_preferences
123      WHERE USER_ID = FND_GLOBAL.USER_ID
124        AND RESP_ID = FND_GLOBAL.RESP_ID;
125 
126 BEGIN
127 
128    IF (FND_LOG.LEVEL_PROCEDURE >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
129       FND_LOG.STRING(FND_LOG.LEVEL_PROCEDURE,
130                      'fnd.plsql.MO_GLOBAL.POPULATE_ORGS.begin',
131                      'Calling PL/SQL procedure '||
132                      'MO_GLOBAL.POPULATE_ORGS');
133    END IF;
134 
135    --
136    -- Initialize the count of the accessible operating units.
137    --
138    g_ou_count := 0;
139 
140    IF (FND_LOG.LEVEL_STATEMENT >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
141       FND_LOG.STRING(FND_LOG.LEVEL_STATEMENT,
142                      'fnd.plsql.MO_GLOBAL.POPULATE_ORGS.input_parameters',
143                      'p_org_id='||p_org_id_char||
144                      ', p_sp_id='||p_sp_id_char);
145    END IF;
146 
147    --
148    -- SP ID is NOT NULL and ORG ID is NULL or NOT NULL
149    --
150    -- Ignore org_id parameter if passed
151    --
152    IF (p_sp_id_char IS NOT NULL) THEN
153 
154       -- Check if this a view all or global view all organizations
155       -- security profile. For a view all security profile within
156       -- a business group, the business group id is populated.
157 
158       SELECT security_profile_name
159            , business_group_id
160            , view_all_organizations_flag
161         INTO l_sp_name
162            , l_bg_id
163            , p_view_all_org
164         FROM per_security_profiles
165        WHERE security_profile_id = to_number(p_sp_id_char);
166 
167        IF (FND_LOG.LEVEL_EVENT >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
168          FND_LOG.STRING(
169            FND_LOG.LEVEL_EVENT,
170            'fnd.plsql.MO_GLOBAL.POPULATE_ORGS.config',
171            'per_security_profiles.security_profile_name=>'||l_sp_name||
172            ', per_security_profiles.business_group_id=>'||l_bg_id||
173            ', per_security_profiles.view_all_organizations_flag=>'||is_view_all_org);
174        END IF;
175 
176        IF (p_view_all_org = 'Y') THEN
177          IF (l_bg_id IS NOT NULL) THEN
178 
179             -- View all Within the Business Group Case
180             IF (FND_LOG.LEVEL_EVENT >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
181                FND_LOG.STRING(FND_LOG.LEVEL_EVENT,
182                               'fnd.plsql.MO_GLOBAL.POPULATE_ORGS.retrieve_orgs_c3_cursor',
183                               'Retrieving operating units using cursor c3 with arguments:'||
184                               ' l_sp_name='||l_sp_name||
185                               ', l_bg_id='||l_bg_id);
186             END IF;
187 
188             OPEN c3(l_sp_name, l_bg_id);
189             LOOP
190                FETCH c3 BULK COLLECT
191                 INTO t_org_id
192                    , t_ou_name;
193                EXIT WHEN c3%NOTFOUND;
194             END LOOP;
195             CLOSE c3;
196 
197          ELSE
198 
199             -- Global View all Case
200             IF (FND_LOG.LEVEL_EVENT >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
201                FND_LOG.STRING(FND_LOG.LEVEL_EVENT,
202                               'fnd.plsql.MO_GLOBAL.POPULATE_ORGS.retrieve_orgs_c4_cursor',
203                               'Retrieving operating units using cursor c4');
204             END IF;
205 
206             OPEN c4;
207             LOOP
208                FETCH c4 BULK COLLECT
209                 INTO t_org_id
210                    , t_ou_name;
211                EXIT WHEN c4%NOTFOUND;
212             END LOOP;
213             CLOSE c4;
214 
215          END IF; -- for l_bg_id is not null
216 
217       ELSE
218 
219          -- Security Profile based on list or hierarchy Case
220          IF (FND_LOG.LEVEL_EVENT >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
221             FND_LOG.STRING(FND_LOG.LEVEL_EVENT,
222                            'fnd.plsql.MO_GLOBAL.POPULATE_ORGS.retrieve_orgs_c1_cursor',
223                            'Retrieving operating units using cursor c1');
224          END IF;
225 
226          OPEN c1;
227          LOOP
228             FETCH c1 BULK COLLECT
229              INTO t_org_id
230                 , t_ou_name;
231             EXIT WHEN c1%NOTFOUND;
232          END LOOP;
233          CLOSE c1;
234 
235       END IF; -- for is_view_all_org
236 
237    --
238    -- SP ID is NULL and ORG ID is NOT NULL
239    --
240    ELSE
241       IF (p_org_id_char is NOT NULL) THEN
242          IF (FND_LOG.LEVEL_EVENT >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
243             FND_LOG.STRING(FND_LOG.LEVEL_EVENT,
244                            'fnd.plsql.MO_GLOBAL.POPULATE_ORGS.retrieve_orgs_c2_cursor',
245                            'Retrieving operating units using cursor c2');
246          END IF;
247 
248          OPEN c2;
249          LOOP
250             FETCH c2 BULK COLLECT
251              INTO t_org_id
252                 , t_ou_name;
253             EXIT WHEN c2%NOTFOUND;
254          END LOOP;
255          CLOSE c2;
256       END IF;
257 
258    END IF;
259 
260    --
261    -- Populate Org Information in MO_GLOB_ORG_ACCESS_TMP
262    --
263    -- Bug fix 4511279
264    --   Need to populate temp table even when access mode is "S"
265    --
266    IF t_org_id.COUNT >= 1 THEN
267 
268       OPEN c5;
269       LOOP
270          FETCH c5 BULK COLLECT
271            into t_pref_org_id;
272          EXIT WHEN c5%NOTFOUND;
273       END LOOP;
274       CLOSE c5;
275 
276       IF (t_pref_org_id.COUNT > 0) THEN
277         IF (g_sync <> 'N') THEN
278          sync_ind := 'Y';
279         END IF;
280          for i in t_pref_org_id.FIRST .. t_pref_org_id.LAST LOOP
281             match_ind := 'N';
282             for j in t_org_id.FIRST .. t_org_id.LAST LOOP
283                if t_pref_org_id(i) = t_org_id(j) then
284                   match_ind := 'Y';
285                   t_common_org_id(k) := t_org_id(j);
286                   t_common_ou_name(k) := t_ou_name(j);
287                   k := k+1;
288                   exit;
289                end if;
290             end LOOP;
291             if match_ind = 'N' then
292                t_delete_org_id(l) := t_pref_org_id(i);
293                l := l + 1;
294             end if;
295          END LOOP;
296          -- IF t_delete_org_id.COUNT <> t_pref_org_id.COUNT THEN
297          IF (t_delete_org_id.COUNT > 0) THEN
298             FORALL m IN t_delete_org_id.FIRST .. t_delete_org_id.LAST
299                delete from FND_MO_SP_PREFERENCES
300                where user_id = FND_GLOBAL.USER_ID
301                and resp_id = FND_GLOBAL.RESP_ID
302                and organization_id = t_delete_org_id(m);
303             commit;
304          END IF;
305       END IF;
306 
307       /*
308       IF (t_pref_org_id.COUNT > 0) and (g_sync <> 'N') THEN
309          sync_ind := 'Y';
310          for i in t_org_id.FIRST .. t_org_id.LAST LOOP
311             for j in t_pref_org_id.FIRST .. t_pref_org_id.LAST LOOP
312                if t_org_id(i) = t_pref_org_id(j) then
313                   t_common_org_id(k) := t_org_id(i);
314                   t_common_ou_name(k) := t_ou_name(i);
315                   k := k+1;
316                   exit;
317                end if;
318             end LOOP;
319          end LOOP;
320       END IF;
321       */
322 
323        IF(sync_ind = 'Y') AND ( t_delete_org_id.COUNT < t_pref_org_id.COUNT) THEN
324           FOR i IN t_common_org_id.FIRST .. t_common_org_id.LAST LOOP
325            INSERT
326              INTO mo_glob_org_access_tmp
327                   (organization_id
328                 ,  organization_name)
329              VALUES (t_common_org_id(i)
330                   ,  t_common_ou_name(i));
331 -- needed for get_ou_tab function
332 	     g_ou_id_tab(i):=t_common_org_id(i);
333           END LOOP;
334        ELSE
335           FOR i IN t_org_id.FIRST .. t_org_id.LAST LOOP
336            INSERT
337              INTO mo_glob_org_access_tmp
338                   (organization_id
339                 ,  organization_name)
340              VALUES (t_org_id(i)
341                   ,  t_ou_name(i));
342 -- needed for get_ou_tab function
343             g_ou_id_tab(i):=t_org_id(i);
344           END LOOP;
345        END IF;
346 
347        g_ou_count := t_org_id.COUNT;
348 
349    END IF;
350 
351 -- set context to 'M' for BG View All Security Profile
352    IF p_sp_id_char IS NOT NULL AND l_bg_id IS NOT NULL AND p_view_all_org = 'Y' THEN
353       p_view_all_org := 'N';
354    END IF;
355 
356 -- setting  init access mode to S, M or A
357    IF p_view_all_org = 'Y' THEN
358        g_init_access_mode:='A';
359    ELSIF g_ou_count = 1 THEN
360       g_init_access_mode:='S';
361    ELSIF g_ou_count > 1  THEN
362       g_init_access_mode:='M';
363    END IF;
364 
365    IF g_ou_count = 1 THEN
366       p_current_org_id := t_org_id(1);
367    END IF;
368 
369    IF (FND_LOG.LEVEL_EVENT >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
370          FND_LOG.STRING(FND_LOG.LEVEL_EVENT,
371                         'fnd.plsql.MO_GLOBAL.POPULATE_ORGS.temp_table_insert',
372                         'Inserted '||g_ou_count||' record(s) into MO_GLOB_ORG_ACCESS_TMP');
373    END IF;
374 
375    IF (FND_LOG.LEVEL_PROCEDURE >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
376       FND_LOG.STRING(FND_LOG.LEVEL_PROCEDURE,
377                      'fnd.plsql.MO_GLOBAL.POPULATE_ORGS.end',
378                      'Returning from PL/SQL procedure '||
379                      'MO_GLOBAL.POPULATE_ORGS: '||
380                      'l_bg_id='||l_bg_id||
381                      ', p_sp_id_char='||p_sp_id_char||
382                      ', l_sp_name='||l_sp_name||
383                      ', p_org_id_char='||p_org_id_char||
384                      ', is_view_all_org='||is_view_all_org);
385    END IF;
386 
387 EXCEPTION
388    WHEN OTHERS THEN
389      IF (FND_LOG.LEVEL_EVENT >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
390               FND_LOG.STRING(FND_LOG.LEVEL_EVENT,
391                              'fnd.plsql.MO_GLOBAL.POPULATE_ORGS.temp_table',
392                              'temporary table other exception raised sqlerrm'||
393                              '=>'||sqlerrm);
394      END IF;
395      generic_error('MO_GLOBAL.POPULATE_ORGS', sqlcode, sqlerrm);
396 
397 END populate_orgs;
398 
399 
400 --
401 --   This is an internal API that deletes the temporary table data
402 --
403 PROCEDURE delete_orgs
404 IS
405 BEGIN
406    --
407    -- Remove all entries from the session specific temporary table.
408    -- Without this, when you switch responsibility you get ORA error
409    -- since the repopulation fails because of the unique constraint
410    -- violation.
411    --
412 
413    IF (FND_LOG.LEVEL_EVENT >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
414       FND_LOG.STRING(FND_LOG.LEVEL_EVENT,
415                      'fnd.plsql.MO_GLOBAL.DELETE_ORGS.begin',
416                      'Before flushing MO_GLOB_ORG_ACCESS_TMP');
417    END IF;
418 
419    DELETE FROM mo_glob_org_access_tmp;
420 
421    IF (FND_LOG.LEVEL_EVENT >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
422       FND_LOG.STRING(FND_LOG.LEVEL_EVENT,
423                      'fnd.plsql.MO_GLOBAL.DELETE_ORGS.end',
424                      'MO_GLOB_ORG_ACCESS_TMP was flushed');
425    END IF;
426 
427 EXCEPTION
428    WHEN OTHERS THEN
429      generic_error('MO_GLOBAL.DELETE_ORGS', sqlcode, sqlerrm);
430 
431 END delete_orgs;
432 
433 --
434 -- Public functions and procedures
435 --
436 
437 --
438 -- Name
439 --   is_multi_org_enabled
440 -- Purpose
441 --   This function determines whether this is a multi-org database
442 --   instance or not. Returns 'Y' or 'N'.
443 --
444 FUNCTION is_multi_org_enabled RETURN VARCHAR2
445 IS
446 
447 BEGIN
448    IF (g_multi_org_flag IS NULL) THEN
449       SELECT nvl(multi_org_flag, 'N')
450         INTO g_multi_org_flag
451         FROM fnd_product_groups;
452    END IF;
453 
454    RETURN g_multi_org_flag;
455 
456 EXCEPTION
457    WHEN OTHERS THEN
458      generic_error('MO_GLOBAL.IS_ACCESS_CONTROL_ENABLED', sqlcode, sqlerrm);
459 END;
460 
461 --
462 -- Name
463 --   set_org_access
464 --
465 -- Purpose
466 --   This procedure determines which operating units can be accessed
467 --   from the current database session. It is called by
468 --   mo_global.init when an Oracle Applications session is started.
469 --   The parameters passed to set_org_access() are the values of the
470 --   MO: Operating Unit, MO: Security Profile profile options and
471 --   Application Owner.
472 --
473 --   If the application being initialized can handle more than one
474 --   Operating Unit, access will be allowed for the Operating Units
475 --   encompassed by the security profile (if specified) and the value of
476 --   the Operating Unit parameter will be ignored, provided access is
477 --   enabled for the application calling this api. If no security profile
478 --   is specified, access will be initialized for the Operating Unit
479 --   only. If both are unspecified an exception will be raised. If
480 --   Application owner is not passed, critical error will be raised.
481 --
482 --   The Multi-Org temporary table data is deleted first for all
483 --   products that call this API.
484 --   This procedure calls another API (populate_orgs) to populate values
485 --   in the Multi-Org temporary table when access control is enabled.
486 --
487 --   For Inquiry only access control for CRM products, care should be
488 --   taken during setup to ensure that the Operating Units included in
489 --   the security profile contain the value specified for the Operating
490 --   Unit parameter. Otherwise, the user will be able to enter records
491 --   for the Operating Unit but will not be able to query the same data
492 --   since read access for CRM is controlled by the security profile.
493 --
494 -- Arguments
495 --   p_org_id_char      - The operating unit ID for the current session
496 --   p_sp_id_char       - The security profile id for the current session
497 --   p_appl_short_name  - Application owner for the current module or session
498 --
499 PROCEDURE set_org_access(p_org_id_char     VARCHAR2,
500                          p_sp_id_char      VARCHAR2,
501                          p_appl_short_name VARCHAR2)
502 IS
503   PRAGMA  AUTONOMOUS_TRANSACTION;
504   l_access_ctrl_enabled    VARCHAR2(1);
505   l_security_profile_id    fnd_profile_option_values.profile_option_value%TYPE := p_sp_id_char;
506   l_org_id                 fnd_profile_option_values.profile_option_value%TYPE := p_org_id_char;
507 
508   l_current_org_id         hr_operating_units.name%TYPE;
509   l_view_all_orgs          VARCHAR2(1);
510 
511   NO_SP_OU_FOUND           EXCEPTION;
512   NO_ORG_ACCESS_FOUND      EXCEPTION;
513   NO_APPL_NAME         EXCEPTION;
514 
515 BEGIN
516    IF (FND_LOG.LEVEL_PROCEDURE >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
517       FND_LOG.STRING(FND_LOG.LEVEL_PROCEDURE,
518                      'fnd.plsql.MO_GLOBAL.SET_ORG_ACCESS.begin',
519                      'Calling PL/SQL procedure MO_GLOBAL.SET_ORG_ACCESS:'||
520                      ' p_org_id_char=>'||p_org_id_char||
521                      ', p_sp_id_char=>'||p_sp_id_char||
522                      ', p_appl_short_name=>'||p_appl_short_name);
523    END IF;
524 
525    IF is_multi_org_enabled <> 'Y' THEN
526       RETURN;
527    END IF;
528 
529    IF p_org_id_char IS NULL AND p_sp_id_char IS NULL THEN
530      RAISE NO_SP_OU_FOUND;
531    ELSIF p_appl_short_name IS NULL THEN
532      RAISE NO_APPL_NAME;  -- Should we seed a new mesg ???
533    END IF;
534    --
535    -- Replace this code with 10g shared globals
536    --
537    BEGIN
538      SELECT nvl(mpi.status, 'N')
539        INTO l_access_ctrl_enabled
540        FROM fnd_mo_product_init mpi
541       WHERE mpi.application_short_name = p_appl_short_name;
542    EXCEPTION
543      WHEN NO_DATA_FOUND THEN
544        fnd_message.set_name('FND','FND_MO_NO_APPL_NAME_FOUND'); -- raise error to
545        app_exception.raise_exception;                       -- enforce MO registration
546      WHEN OTHERS THEN
547        generic_error('MO_GLOBAL.SET_ORG_ACCESS', sqlcode, sqlerrm);
548    END;
549 
550    IF (FND_LOG.LEVEL_PROCEDURE >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
551          FND_LOG.STRING(FND_LOG.LEVEL_PROCEDURE,
552                         'fnd.plsql.MO_GLOBAL.SET_ORG_ACCESS.access_status',
553                         'Checking access status within PL/SQL procedure '||
554                         'MO_GLOBAL.SET_ORG_ACCESS: '||
555                         'l_access_ctrl_enabled=>'||l_access_ctrl_enabled);
556    END IF;
557 
558    --
559    -- Delete temporary table data first for all products access enabled or not
560    --
561    delete_orgs;
562    IF (FND_LOG.LEVEL_PROCEDURE >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
563          FND_LOG.STRING(FND_LOG.LEVEL_PROCEDURE,
564                         'fnd.plsql.MO_GLOBAL.SET_ORG_ACCESS.after_delete',
565                         'Returning from PL/SQL procedure '||
566                         'MO_GLOBAL.DELETE_ORGS ');
567    END IF;
568    --
569    -- For all products, when the access control feature is enabled,
570    -- 1. Use the MO: Security Profile if it is set.
571    -- 2. Use the MO: Operating Unit if MO: Security Profile is not set
572    --
573    IF (l_access_ctrl_enabled = 'Y') THEN
574      IF l_security_profile_id IS NOT NULL THEN
575        l_org_id := null;
576      END IF;
577      --
578      -- Populate temp table
579      --
580      populate_orgs(l_org_id,
581                    l_security_profile_id,
582                    l_current_org_id,
583                    l_view_all_orgs);
584      IF (FND_LOG.LEVEL_PROCEDURE >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
585          FND_LOG.STRING(FND_LOG.LEVEL_PROCEDURE,
586                         'fnd.plsql.MO_GLOBAL.SET_ORG_ACCESS.After_Populate',
587                         'Returning from PL/SQL procedure '||
588                         'MO_GLOBAL.POPULATE_ORGS ');
589      END IF;
590      --
591      -- Check if you have access to at least one operating unit.
592      --
593      IF g_ou_count = 0 THEN
594        RAISE NO_ORG_ACCESS_FOUND;
595      ELSIF g_ou_count = 1 THEN
596        --
597        -- Set the 'Single' access contexts:
598        --
599        set_policy_context('S', l_current_org_id);
600      ELSE
601        --
602        -- Added code for All mode to avoid using the policy predicate
603        -- when user has access to global view all security profile
604        -- Bug (2720892)
605        -- Set the access contexts:
606        --
607        IF l_view_all_orgs = 'Y' THEN
608          set_policy_context('A','');
609        ELSE
610          set_policy_context('M','');
611        END IF;
612      END IF;
613    ELSE
614      IF l_org_id IS NOT NULL THEN
615         populate_orgs(l_org_id,                 -- Bug4475369 populate
616                       null,                     -- 1 ou for S mode for the
617                       l_current_org_id,         -- timing being.
618                       l_view_all_orgs);
619         set_policy_context('S',l_org_id);
620      END IF;
621    END IF;
622 
623    commit;
624    IF (FND_LOG.LEVEL_PROCEDURE >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
625       FND_LOG.STRING(FND_LOG.LEVEL_PROCEDURE,
626                      'fnd.plsql.MO_GLOBAL.SET_ORG_ACCESS.end',
627                      'Calling PL/SQL procedure MO_GLOBAL.SET_ORG_ACCESS:'||
628                      ' p_org_id_char=>'||p_org_id_char||
629                      ',p_sp_id_char=>'||p_sp_id_char||
630                      ',p_appl_short_name=>'||p_appl_short_name||
631                      ',l_view_all_orgs=>'||l_view_all_orgs||
632                      ',g_ou_count=>'||g_ou_count);
633    END IF;
634 
635 EXCEPTION
636    WHEN NO_ORG_ACCESS_FOUND THEN
637      fnd_message.set_name('FND','MO_ORG_ACCESS_NO_DATA_FOUND');
638      app_exception.raise_exception;
639    WHEN NO_SP_OU_FOUND THEN
640      fnd_message.set_name('FND','MO_ORG_ACCESS_NO_SP_OU_FOUND');
641      app_exception.raise_exception;
642    WHEN NO_APPL_NAME THEN
643      app_exception.raise_exception;
644    WHEN OTHERS THEN
645      generic_error('MO_GLOBAL.SET_ORG_ACCESS', sqlcode, sqlerrm);
646 
647 END set_org_access;
648 
649 
650 
651 --
652 -- Name
653 --   jtt_init
654 -- Purpose
655 --   Initialization code for Organization Security Policy.  This is
656 --   mainly called from JTT java API's.
657 --   This will call the init API and will also initialize ICX sesion attribute
658 --   JTTCURRENTORG when temp table has only one record
659 --
660 PROCEDURE jtt_init(p_appl_short_name  IN VARCHAR2,
661                    p_icx_session_id   IN NUMBER)
662 IS
663 begin
664    init(p_appl_short_name,'Y');
665 
666    if g_current_org_id is not null
667    then
668      fnd_session_management.putSessionAttributeValue(p_name        => 'JTTCURRENTORG',
669                                                      p_value       => g_current_org_id,
670                                                      p_session_id  => p_icx_session_id);
671    end if;
672 end jtt_init;
673 
674 
675 --
676 -- Name
677 --   clear_current_org_context
678 -- Purpose
679 --   This procedure clears the current org context in database session as
680 --   well as reset the ICX session attribute JTTCURRENTORG
681 --
682 PROCEDURE clear_current_org_context(p_icx_session_id   IN NUMBER)
683 IS
684 BEGIN
685   dbms_session.set_context('multi_org2', 'current_org_id', '');
686   fnd_session_management.clearSessionAttributeValue(p_name        => 'JTTCURRENTORG',
687                                                     p_session_id  => p_icx_session_id);
688   g_current_org_id := NULL;
689 END;
690 
691 --
692 -- Name
693 --   init
694 -- Purpose
695 --   Initialization code for Organization Security Policy
696 --
697 PROCEDURE init(p_appl_short_name  VARCHAR2)
698 IS
699 begin
700    init(p_appl_short_name,'Y');
701 end init;
702 
703 PROCEDURE init(p_appl_short_name  VARCHAR2, p_sync VARCHAR2)
704 IS
705 
706    l_security_profile_id  fnd_profile_option_values.profile_option_value%TYPE := NULL;
707    l_org_id               fnd_profile_option_values.profile_option_value%TYPE := NULL;
708 
709 BEGIN
710    --
711    -- Check if multi-org is enabled
712    --
713    IF (FND_LOG.LEVEL_PROCEDURE >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
714       FND_LOG.STRING(FND_LOG.LEVEL_PROCEDURE,
715                      'fnd.plsql.MO_GLOBAL.INIT.begin',
716                      'Calling PL/SQL procedure MO_GLOBAL.INIT');
717    END IF;
718    IF is_multi_org_enabled = 'Y' THEN
719         --
720         -- Get the profile values and call set_org_access API
721         --
722         fnd_profile.get('XLA_MO_SECURITY_PROFILE_LEVEL', l_security_profile_id);
723         fnd_profile.get('ORG_ID', l_org_id);
724 
725         IF (FND_LOG.LEVEL_EVENT >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
726          FND_LOG.STRING(FND_LOG.LEVEL_EVENT,
727                         'fnd.plsql.MO_GLOBAL.INIT.config',
728                         'MO: Operating Unit=>'||l_org_id||
729                         ', MO: Security Profile=>'||l_security_profile_id||
730                         ', p_appl_short_name=>'||p_appl_short_name);
731         END IF;
732         IF p_sync = 'Y' THEN
733            g_sync := 'Y';
734         ELSE
735            g_sync := 'N';
736         END IF;
737         set_org_access(l_org_id, l_security_profile_id, p_appl_short_name);
738 
739         -- store profile and org id in global variables
740         -- used for checking if new initialization is to be done
741         -- in is_mo_init_done API
742         g_old_sp_id:=l_security_profile_id;
743 	IF g_old_sp_id IS NOT NULL THEN
744            g_old_org_id:=NULL;
745 	ELSE
746            g_old_org_id:=l_org_id;
747 	END IF;
748 
749    END IF; -- multi org is enabled
750    IF (FND_LOG.LEVEL_PROCEDURE >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
751       FND_LOG.STRING(FND_LOG.LEVEL_PROCEDURE,
752                      'fnd.plsql.MO_GLOBAL.INIT.end',
753                      'Exiting PL/SQL procedure MO_GLOBAL.INIT');
754    END IF;
755 EXCEPTION
756    WHEN others THEN
757      generic_error('MO_GLOBAL.INIT', sqlcode, sqlerrm);
758 END init;
759 
760 
761 --
762 -- Name
763 --   org_security
764 --
765 -- Purpose
766 --   This function implements the security policy for the Multi-Org
767 --   Access Control mechanism. It is automatically called by the oracle
768 --   server whenever a secured table or view is referenced by a SQL
769 --   statement. Products should not call this function directly.
770 --
771 --   The security policy function is expected to return a predicate
772 --   (a WHERE clause) that will control which records can be accessed
773 --   or modified by the SQL statement. After incorporating the
774 --   predicate, the server will parse, optimize and execute the
775 --   modified statement.
776 --
777 -- Arguments
778 --   obj_schema - the schema that owns the secured object
779 --   obj_name   - the name of the secured object
780 --
781 FUNCTION org_security(obj_schema VARCHAR2,
782 		      obj_name   VARCHAR2) RETURN VARCHAR2
783 IS
784 l_ci_debug  fnd_profile_option_values.profile_option_value%TYPE := NULL;
785 BEGIN
786 
787   --
788   --  Returns different predicates based on the access_mode
789   --  The codes for access_mode are
790   --  M - Multiple OU Access
791   --  A - All OU Access
792   --  S - Single OU Access
793   --  Null - Backward Compatibility - CLIENT_INFO case
794   --
795   --  The Predicates will be appended to Multi-Org synonyms
796 
797   IF obj_name = 'AR_PAYMENT_SCHEDULES' and g_access_mode='S' THEN
798       RETURN 'org_id = sys_context(''multi_org2'',''current_org_id'') OR (org_id = -3116)';
799 
800   ELSIF g_access_mode IS NOT NULL THEN
801     IF g_access_mode = 'M' THEN
802       RETURN 'EXISTS (SELECT 1
803                         FROM mo_glob_org_access_tmp oa
804                        WHERE oa.organization_id = org_id)';
805     ELSIF g_access_mode in ('A','B') THEN
806       RETURN 'org_id <> -3113';           -- Bug5109430 filter seed data from policy predicate
807     ELSIF g_access_mode = 'S' THEN
808       RETURN 'org_id = sys_context(''multi_org2'',''current_org_id'')';
809     ELSIF g_access_mode = 'X' THEN
810       RETURN '1 = 2';
811     END IF;
812 
813   ELSE       -- This section is used reserved for debugging using CLIENT_INFO
814 
815    --
816    -- Interim solution for MFG teams
817    --
818    fnd_profile.get('FND_MO_INIT_CI_DEBUG', l_ci_debug);
819    IF l_ci_debug = 'Y' THEN
820       RETURN 'org_id = substrb(userenv(''CLIENT_INFO''),1,10)';
821    ELSE
822       RETURN '1=2';
823    END IF;
824 
825   END IF;
826 
827 END org_security;
828 
829 
830 --
831 -- Name
832 --   set_org_context
833 -- Purpose
834 --   Wrapper procedure for setting up the Operating Unit context in the client
835 --   info area and organization access list for Multi-Org Access Control for CRM
836 --   introduced in 11i.1
837 --
838 -- Arguments
839 --   p_org_id_char      - org_id for the operating unit; can be up to 10
840 --                        bytes long
841 --   p_sp_id_char       - MO: Security profile id
842 --   p_appl_short_name  - Application owner for the current module or session
843 --
844 PROCEDURE set_org_context(p_org_id_char     VARCHAR2,
845                           p_sp_id_char      VARCHAR2,
846                           p_appl_short_name VARCHAR2) is
847 
848    l_ci_debug  fnd_profile_option_values.profile_option_value%TYPE := NULL;
849 
850 BEGIN
851   IF (FND_LOG.LEVEL_EVENT >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
852          FND_LOG.STRING(FND_LOG.LEVEL_EVENT,
853                         'fnd.plsql.MO_GLOBAL.INIT.config',
854                         'MO: Operating Unit=>'||p_org_id_char||
855                         ',MO: Security Profile=>'||p_sp_id_char||
856                         ',p_appl_short_name=>'||p_appl_short_name);
857   END IF;
858 
859    fnd_profile.get('FND_MO_INIT_CI_DEBUG', l_ci_debug);
860    -- Set up the Operating Unit context in the client info area
861    IF l_ci_debug = 'Y' THEN
862      fnd_client_info.set_org_context(p_org_id_char);
863    END IF;
864 
865    -- Set up the organization access list for Multi- Org Access Control
866    set_org_access(p_org_id_char,p_sp_id_char, p_appl_short_name);
867 
868    IF (FND_LOG.LEVEL_PROCEDURE >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
869       FND_LOG.STRING(FND_LOG.LEVEL_PROCEDURE,
870                      'fnd.plsql.MO_GLOBAL.SET_ORG_CONTEXT.end',
871                      'Returning from PL/SQL procedure MO_GLOBAL.SET_ORG_CONTEXT');
872    END IF;
873 
874 END set_org_context;
875 
876 
877 --
878 -- Name
879 --   check_access
880 -- Purpose
881 --   Checks
882 --  1. if an Operating Unit exists in the PL/SQL array.
883 --     The PL/SQL array is populated by the set_org_access Multi-Org API.
884 --  2. if Operating Unit is same as current org id for 'S'ingle org initialization
885 --
886 -- Arguments
887 --   p_org_id         - org_id for the Operating Unit
888 --
889 FUNCTION check_access(p_org_id    NUMBER)
890 RETURN VARCHAR2 IS
891 
892 l_org_exists   varchar2(1);
893 
894 BEGIN
895     IF g_access_mode = 'A' THEN
896 -- if access mode is ALL then return true
897           RETURN 'Y';
898 
899     ELSIF (GET_OU_COUNT > 1) OR (g_access_mode = 'M') THEN -- added g_access_mode for Bug4575131
900 -- if mo initialization is done
901 
902 	  SELECT 'Y'
903 	    INTO l_org_exists
904 	    FROM mo_glob_org_access_tmp
905 	   WHERE organization_id = p_org_id;
906 	  RETURN 'Y';
907 
908     ELSIF GET_CURRENT_ORG_ID IS NOT NULL THEN
909 -- if mo initialization is not done but context is set to 'S'
910 
911 	  IF P_ORG_ID = GET_CURRENT_ORG_ID THEN
912 	     RETURN 'Y';
913 	  END IF;
914 
915     END IF;
916 
917     RETURN 'N';
918 
919 EXCEPTION
920   WHEN NO_DATA_FOUND THEN
921     RETURN 'N';
922   WHEN VALUE_ERROR THEN
923     RETURN 'N';
924 END;
925 
926 --
927 -- Name
928 --   get_ou_name
929 -- Purpose
930 --   This function returns the Operating Unit name for the org_id parameter
931 --   passed, if it exists in the temporary table populated by
932 --   set_org_access Multi-Org API.
933 --
934 -- Arguments
935 --   p_org_id         - org_id for the Operating Unit
936 --
937 FUNCTION get_ou_name(p_org_id    NUMBER)
938 RETURN VARCHAR2 IS
939 
940 l_ou_name      mo_glob_org_access_tmp.organization_name%TYPE;
941 
942 BEGIN
943 
944   SELECT organization_name
945     INTO l_ou_name
946     FROM mo_glob_org_access_tmp
947    WHERE organization_id = p_org_id;
948   RETURN l_ou_name;
949 
950 EXCEPTION
951   WHEN NO_DATA_FOUND THEN
952     RETURN NULL;
953   WHEN VALUE_ERROR THEN
954     RETURN NULL;
955 END;
956 
957 --
958 -- Name
959 --   check_valid_org
960 -- Purpose
961 --   Checks if the specified operating unit exists in the session's
962 --   access control list. This function is equivalent to the
963 --   check_access function but also posts an error message if the
964 --   specified operating unit is null or not in the access list.
965 --   The calling application can check the returned value of the
966 --   function and raise an error if it is 'N'.
967 --
968 -- Arguments
969 --   p_org_id         - org_id for the Operating Unit
970 --
971 FUNCTION check_valid_org(p_org_id NUMBER) RETURN VARCHAR2
972 IS
973 
974 BEGIN
975    IF (p_org_id is null) THEN
976       -- Post an error message and return:
977       fnd_message.set_name('FND', 'MO_ORG_REQUIRED');
978       FND_MSG_PUB.ADD;
979       RETURN 'N';
980    END IF;
981 
982    IF (check_access(p_org_id) = 'Y') THEN
983       RETURN 'Y';
984    END IF;
985 
986    -- Post an error message and return:
987    fnd_message.set_name('FND', 'MO_ORG_INVALID');
988    FND_MSG_PUB.ADD;
989    RETURN 'N';
990 END;
991 
992 --
993 -- Name
994 --   set_policy_context
995 -- Purpose
996 --   Sets the application context for the current org and the access
997 --   mode to be used in server side code for validations as well as in
998 --   the Multi-Org security policy function.
999 --
1000 -- Arguments
1001 --   p_access_mode    - specifies the operating unit access. 'S' for
1002 --                      Single, 'M' for Multiple, 'A' for All.
1003 --                    - Access Mode All is resrved for future use.
1004 --                    - X is used to prevent returning any data from synonym
1005 --   p_org_id         - org_id of the operating unit.
1006 --
1007 PROCEDURE set_policy_context(p_access_mode VARCHAR2,
1008                              p_org_id      NUMBER)
1009 IS
1010 
1011 BEGIN
1012   IF (FND_LOG.LEVEL_PROCEDURE >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
1013       FND_LOG.STRING(FND_LOG.LEVEL_PROCEDURE,
1014                      'fnd.plsql.MO_GLOBAL.SET_POLICY_CONTEXT.begin',
1015                      'Calling PL/SQL procedure MO_GLOBAL.SET_POLICY_CONTEXT:'||
1016                      ' p_access_mode=>'||p_access_mode||
1017                      ',p_org_id=>'||p_org_id);
1018   END IF;
1019   --
1020   -- Get the present values of access mode and current org id
1021   --
1022   IF (p_access_mode = g_access_mode
1023       and p_org_id = g_current_org_id
1024       and sys_context('multi_org2','current_org_id') = p_org_id) THEN
1025 
1026          NULL;  -- Bug5582505: quick exit if nothing to be reset
1027   ELSIF (p_access_mode = 'S') THEN
1028     IF (g_access_mode is NULL OR g_access_mode <> 'S') THEN
1029       --
1030       -- If single operating unit access, then mode should be set to 'S'
1031       --
1032       dbms_session.set_context('multi_org', 'access_mode', p_access_mode);
1033       g_access_mode := p_access_mode;
1034     END IF;
1035     IF (g_current_org_id IS NULL OR g_current_org_id <> p_org_id
1036        OR sys_context('multi_org2','current_org_id') <> p_org_id   -- Bug4916086
1037        OR sys_context('multi_org2','current_org_id') is null) THEN
1038       --
1039       -- Set the current org context
1040       --
1041       dbms_session.set_context('multi_org2', 'current_org_id', p_org_id);
1042       g_current_org_id := p_org_id;
1043       -- Bug 	7227733 Passing current org id to FND
1044      fnd_global.initialize('ORG_ID',g_current_org_id);
1045 
1046     END IF;
1047 
1048   ELSIF (p_access_mode = 'M') THEN
1049     IF (g_access_mode is NULL OR g_access_mode <> 'M') THEN
1050       --
1051       -- If multiple operating units access, then mode should be set to 'M'
1052       --
1053       dbms_session.set_context('multi_org', 'access_mode', p_access_mode);
1054       g_access_mode := p_access_mode;
1055     END IF;
1056     IF (g_current_org_id IS NOT NULL ) THEN
1057       --
1058       -- Unset the current org context, since it is not required for multiple
1059       -- access
1060       --
1061       dbms_session.set_context('multi_org2', 'current_org_id', '');
1062       g_current_org_id := NULL;
1063        -- Bug 	7227733 Passing current org id to FND
1064      fnd_global.initialize('ORG_ID',g_current_org_id);
1065     END IF;
1066 
1067   ELSIF (p_access_mode = 'A') and g_init_access_mode = 'A' THEN
1068     IF (g_access_mode is NULL OR g_access_mode <> 'A') THEN
1069       --
1070       -- If all operating units access, then mode should be set to 'A'
1071       --
1072       dbms_session.set_context('multi_org', 'access_mode', p_access_mode);
1073       g_access_mode := p_access_mode;
1074     END IF;
1075     IF (g_current_org_id IS NOT NULL ) THEN
1076       --
1077       -- Unset the current org context, since it is not required for all
1078       -- access
1079       --
1080       dbms_session.set_context('multi_org2', 'current_org_id', '');
1081       g_current_org_id := NULL;
1082        -- Bug 	7227733 Passing current org id to FND
1083      fnd_global.initialize('ORG_ID',g_current_org_id);
1084     END IF;
1085 
1086   ELSIF (p_access_mode in ('X','B')) THEN
1087       if sys_context('multi_org2','current_org_id') is not null then
1088          dbms_session.set_context('multi_org2', 'current_org_id', '');
1089       end if;
1090 
1091       dbms_session.set_context('multi_org', 'access_mode', p_access_mode);
1092       g_current_org_id := NULL;
1093       g_access_mode := p_access_mode;
1094 
1095   ELSIF (p_access_mode is NULL) THEN
1096     IF (g_access_mode IS NOT NULL) THEN
1097       --
1098       -- If access_mode is not passed, then unset it
1099       --
1100       dbms_session.set_context('multi_org', 'access_mode', p_access_mode);
1101       g_access_mode := p_access_mode;
1102     END IF;
1103     IF (g_current_org_id IS NOT NULL ) THEN
1104       --
1105       -- Unset the current org context, since it is not required when mode
1106       -- is not set
1107       --
1108       dbms_session.set_context('multi_org2', 'current_org_id', '');
1109       g_current_org_id := NULL;
1110        -- Bug 	7227733 Passing current org id to FND
1111      fnd_global.initialize('ORG_ID',g_current_org_id);
1112     END IF;
1113 
1114   END IF;
1115 
1116 --
1117 -- store the user and resp. IDs, to be used for checking new OA user session
1118 -- in is_mo_init_done API
1119 --
1120         g_old_user_id:=sys_context('FND','USER_ID');
1121         g_old_resp_id:=sys_context('FND','RESP_ID');
1122 
1123   IF (FND_LOG.LEVEL_PROCEDURE >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
1124       FND_LOG.STRING(FND_LOG.LEVEL_PROCEDURE,
1125                      'fnd.plsql.MO_GLOBAL.SET_POLICY_CONTEXT.end',
1126                      'Returning from PL/SQL prcedure MO_GLOBAL.SET_POLICY_CONTEXT');
1127   END IF;
1128 
1129 END set_policy_context;
1130 
1131 --
1132 -- Name
1133 --   get_current_org_id
1134 -- Purpose
1135 --   This function returns the current_org_id stored in the application
1136 --   context.
1137 --
1138 FUNCTION get_current_org_id RETURN NUMBER
1139 IS
1140 
1141 BEGIN
1142    RETURN to_number(g_current_org_id);
1143 EXCEPTION
1144    WHEN NO_DATA_FOUND THEN
1145      RETURN NULL;
1146    WHEN VALUE_ERROR THEN
1147      RETURN NULL;
1148 END get_current_org_id;
1149 
1150 --
1151 -- Name
1152 --   get_access_mode
1153 -- Purpose
1154 --   This function returns the access mode stored in the application
1155 --   context.
1156 --
1157 FUNCTION get_access_mode RETURN VARCHAR2
1158 IS
1159 
1160 BEGIN
1161    RETURN (g_access_mode);
1162 EXCEPTION
1163    WHEN NO_DATA_FOUND THEN
1164      RETURN NULL;
1165    WHEN VALUE_ERROR THEN
1166      RETURN NULL;
1167 END get_access_mode;
1168 
1169 
1170 --
1171 -- Name
1172 --   get_ou_count
1173 -- Purpose
1174 --   This function returns the count of the records stored in the Multi-Org
1175 --   temporary table.
1176 --
1177 FUNCTION get_ou_count RETURN NUMBER
1178 IS
1179 
1180 BEGIN
1181   RETURN (g_ou_count);
1182 EXCEPTION
1183   WHEN NO_DATA_FOUND THEN
1184     RETURN 0;
1185   WHEN VALUE_ERROR THEN
1186     RETURN 0;
1187 END get_ou_count;
1188 
1189 --
1190 -- Name
1191 --   get_valid_org
1192 -- Purpose
1193 --   This function determines and returns the valid ORG_ID.
1194 --
1195 FUNCTION get_valid_org(p_org_id      NUMBER) RETURN NUMBER
1196 IS
1197 
1198   l_org_id           NUMBER;
1199   l_status           VARCHAR2(1);
1200 
1201 BEGIN
1202   --
1203   -- Debug information
1204   --
1205   IF (FND_LOG.LEVEL_PROCEDURE >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
1206       FND_LOG.STRING(FND_LOG.LEVEL_PROCEDURE,
1207                      'fnd.plsql.MO_GLOBAL.GET_VALID_ORG.begin',
1208                      'Calling PL/SQL function '||
1209                      'MO_GLOBAL.GET_VALID_ORG'||
1210                      ' p_org_id=>'||p_org_id);
1211   END IF;
1212 
1213   --
1214   -- Obtain org ID in the following order:
1215   --  1. parameter from caller
1216   --  2. current org ID
1217   --  3. default org ID
1218   --
1219   IF (p_org_id = FND_API.G_MISS_NUM) THEN
1220     --
1221     -- If p_org_id is G_MISS_NUM (org id is not passed in), then get the org_id
1222     -- from current org_id. If that is also not available, get the default
1223     -- org_id
1224     --
1225     l_org_id := NVL(mo_global.get_current_org_id,
1226                     mo_utils.get_default_org_id);
1227   ELSE
1228     --
1229     -- If p_org_id is null or different from G_MISS_NUM
1230     -- use explicitly passed in org_id
1231     --
1232     l_org_id := p_org_id;
1233   END IF;
1234 
1235   --
1236   -- Now validate the org ID
1237   --
1238   l_status := check_valid_org(l_org_id);
1239 
1240   --
1241   --  If the org_id is valid, return it. If it's invalid, return NULL
1242   --
1243   IF (l_status = 'N') THEN
1244     --
1245     -- Debug information
1246     --
1247     IF (FND_LOG.LEVEL_PROCEDURE >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
1248         FND_LOG.STRING(FND_LOG.LEVEL_PROCEDURE,
1249                      'fnd.plsql.MO_GLOBAL.GET_VALID_ORG.end',
1250                      'Returning from PL/SQL function '||
1251                      'MO_GLOBAL.GET_VALID_ORG:'||
1252                      ' Returns NULL');
1253     END IF;
1254 
1255     --
1256     -- Org_id is invalid
1257     --
1258     RETURN NULL;
1259 
1260   ELSE
1261     --
1262     -- Debug information
1263     --
1264     IF (FND_LOG.LEVEL_PROCEDURE >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
1265         FND_LOG.STRING(FND_LOG.LEVEL_PROCEDURE,
1266                      'fnd.plsql.MO_GLOBAL.GET_VALID_ORG.end',
1267                      'Returning from PL/SQL function '||
1268                      'MO_GLOBAL.GET_VALID_ORG:'||
1269                      ' Returns '||l_org_id);
1270     END IF;
1271 
1272     --
1273     -- Org_id is valid
1274     --
1275     RETURN l_org_id;
1276 
1277   END IF;
1278 
1279 EXCEPTION
1280    WHEN OTHERS THEN
1281      generic_error('MO_GLOBAL.Get_Valid_Org', sqlcode, sqlerrm);
1282 
1283 END get_valid_org;
1284 
1285 --  validate_orgid_pub_api
1286 --  to be used in public API's for backword compatibilty
1287 --
1288 --  STATUS is 'S'uccess if org_id passed was
1289 --   1. either valid w/ MO:SP or CURRENT ORG or MO:OU
1290 --    OR
1291 --   2. we have derived from CURRENT ORG or MO:Def OU  or MO:OU
1292 --
1293 --  STATUS is 'F'ailure if org_id passed was
1294 --   1. either invalid w/ both MO:SP and CURRENT ORG and MO:OU
1295 --    OR
1296 --   2. we could not derive that
1297 --
1298 --  To suppress the error pass ERROR_MESG_SUPPR as 'Y'
1299 --   arguments
1300 --  ORG_ID            org_id for Operating Unit
1301 --  ERROR_MESG_SUPPR  error message suppresser
1302 --  STATUS            validation/derivation result
1303 --
1304 
1305 PROCEDURE validate_orgid_pub_api(ORG_ID             IN OUT NOCOPY NUMBER,
1306 				ERROR_MESG_SUPPR    IN VARCHAR2  DEFAULT 'N',
1307 				STATUS              OUT NOCOPY VARCHAR2)
1308 IS
1309 l_org_id number(15);
1310 ORG_ID_INVALID_OR_NON_DRV EXCEPTION;
1311 
1312 BEGIN
1313 
1314 
1315 /* May consider the following logic to execute MO init w/in the proc in future.
1316 
1317   IF g_ou_count = 0 AND
1318      FND_PROFILE.VALUE('XLA_MO_SECURITY_PROFILE_LEVEL') is NOT NULL THEN
1319      mo_global.init('M');
1320 
1321   ELSIF g_ou_count = 0 AND
1322      FND_PROFILE.VALUE('XLA_MO_SECURITY_PROFILE_LEVEL') is NULL AND
1323      FND_PROFILE.VALUE('ORG_ID') is NOT NULL THEN
1324      mo_global.init('S');
1325   END IF;
1326 */
1327 
1328   STATUS := 'F'; -- initialize the variable to F
1329 
1330   IF FND_PROFILE.VALUE('XLA_MO_SECURITY_PROFILE_LEVEL') is NOT NULL
1331      AND g_ou_count = 0 THEN
1332         FND_MESSAGE.SET_NAME('FND','FND_MO_NOINIT_SP_PUB_API');
1333         FND_MSG_PUB.ADD;
1334         APP_EXCEPTION.RAISE_EXCEPTION;
1335   END IF;
1336 
1337 -- if org_id is passed explicitly
1338   IF ORG_ID IS NOT NULL AND ORG_ID <> FND_API.G_MISS_NUM THEN
1339      STATUS:='F';
1340 -- check if org_id passed is valid with
1341 --           1. temp table
1342 --           2. current_org_id
1343 --           3. MO: OU
1344 
1345 -- if mo init is done either w/ 'M'ultiple or 'S'ingle
1346 -- check if org_id is valid with orgs in temp table or in the current org
1347 
1348      IF g_ou_count >=1 THEN
1349        IF CHECK_ACCESS(ORG_ID) = 'Y' THEN
1350           STATUS:='S';
1351        ELSE
1352           IF ERROR_MESG_SUPPR = 'N' THEN
1353             FND_MESSAGE.SET_NAME('FND','FND_MO_INVALID_OU_API');
1354             FND_MESSAGE.SET_TOKEN('ORG_NAME', mo_utils.get_org_name(ORG_ID));
1355             FND_MESSAGE.SET_TOKEN('ORG_ID', ORG_ID);
1356             FND_MSG_PUB.ADD;
1357             APP_EXCEPTION.RAISE_EXCEPTION;
1358           END IF;
1359       END IF;
1360 
1361      ELSIF FND_PROFILE.VALUE('XLA_MO_SECURITY_PROFILE_LEVEL') is NULL THEN
1362         -- mo initialization is not done.
1363         -- check if org_id passed id valid with MO:OU
1364         -- for backword compatibilty
1365         FND_PROFILE.GET('ORG_ID',l_org_id);
1366         IF ORG_ID = l_org_id THEN
1367           set_policy_context('S',l_org_id);  -- setting org context for synonym
1368           STATUS := 'O';
1369 
1370         END IF;
1371 
1372       END IF;
1373 
1374    ELSE  -- org_id value is not passed in explicitly.
1375          -- try getting the org_id from
1376          --           1. current org id
1377          --           2. MO: Def OU
1378          --           3. MO: OU
1379     STATUS:='F';
1380       -- looking here for current org id otherwise default OU
1381       -- if initialization is done
1382       IF g_ou_count >= 1 THEN
1383          ORG_ID := mo_global.get_current_org_id;
1384          IF ORG_ID is NOT NULL THEN
1385             STATUS := 'C';
1386          ELSE
1387             ORG_ID := GET_VALID_ORG(FND_API.G_MISS_NUM);
1388             IF ORG_ID is NOT NULL THEN
1389                STATUS := 'D';
1390             END IF;
1391          END IF;
1392 
1393       -- for backword compatibility support. Return status O
1394       ELSIF FND_PROFILE.VALUE('XLA_MO_SECURITY_PROFILE_LEVEL') is NULL THEN
1395         FND_PROFILE.GET('ORG_ID',l_org_id);
1396         ORG_ID := l_org_id;
1397         set_policy_context('S',l_org_id);  -- setting org context for synonym
1398         STATUS := 'O';
1399       END IF;
1400 
1401     END IF;
1402 
1403 
1404 IF STATUS='F' AND ERROR_MESG_SUPPR = 'N' THEN
1405       FND_MESSAGE.SET_NAME('FND','FND_MO_INVALID_OU_PUB_API');
1406       FND_MSG_PUB.ADD;
1407       APP_EXCEPTION.RAISE_EXCEPTION;
1408 --     RAISE ORG_ID_INVALID_OR_NON_DRV;
1409 END IF;
1410 
1411 EXCEPTION
1412   WHEN ORG_ID_INVALID_OR_NON_DRV THEN
1413       FND_MESSAGE.SET_NAME('FND','FND_MO_INVALID_OU_PUB_API');
1414       APP_EXCEPTION.RAISE_EXCEPTION;
1415    WHEN others THEN
1416      STATUS:='F';
1417      generic_error('MO_GLOBAL.VALIDATE_ORGID_PUB_API', sqlcode, sqlerrm);
1418 
1419 END validate_orgid_pub_api;
1420 
1421 --  Name: is_mo_init_done
1422 --  Purpose: check if MO initialization is done
1423 --  if OA user session is different then check if SP is same, return Y if same
1424 --  Order is
1425 --  Temp table -> Current Org -> Access Mode (e.g S, M or A)
1426 --
1427 
1428 FUNCTION is_mo_init_done RETURN VARCHAR2
1429 IS
1430 l_current_sp_id fnd_profile_option_values.profile_option_value%TYPE := NULL;
1431 l_current_org_id  fnd_profile_option_values.profile_option_value%TYPE := NULL;
1432 l_user_id NUMBER:=NULL;
1433 l_resp_id NUMBER:=NULL;
1434 BEGIN
1435 --
1436 -- bug#5677563 - check for different user sessions, if SP/OU is same
1437 -- if SP is not same application should re-initialize the MOAC
1438 -- hence return 'N'
1439 --
1440 
1441    fnd_profile.get('XLA_MO_SECURITY_PROFILE_LEVEL', l_current_sp_id);
1442    fnd_profile.get('ORG_ID', l_current_org_id);
1443 
1444    l_user_id:=sys_context('FND','USER_ID');
1445    l_resp_id:=sys_context('FND','RESP_ID');
1446 
1447    IF (g_ou_count >= 1) THEN
1448    IF l_current_sp_id IS NOT NULL AND  l_current_sp_id <> FND_API.G_MISS_NUM THEN
1449      IF nvl(g_old_sp_id,-1) <> l_current_sp_id THEN
1450       return 'N';
1451      END IF;
1452    ELSIF l_current_org_id IS NOT NULL AND l_current_org_id <> FND_API.G_MISS_NUM THEN
1453      IF nvl(g_old_org_id,-1) <> l_current_org_id THEN
1454         return 'N';
1455      END IF;
1456    ELSE
1457         return 'N';
1458    END IF;
1459    ELSIF( g_current_org_id is not null  OR g_access_mode = 'A' )THEN
1460         IF (nvl(g_old_user_id,-1) <> l_user_id ) OR (nvl(g_old_resp_id,-1) <> l_resp_id) THEN
1461             return 'N';
1462         END IF;
1463    ELSE
1464       return 'N';
1465 
1466    IF (FND_LOG.LEVEL_PROCEDURE >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
1467       FND_LOG.STRING(FND_LOG.LEVEL_PROCEDURE,
1468                  'fnd.plsql.MO_GLOBAL.is_mo_init_done.begin',
1469                      'g_ou_count=>'||g_ou_count||
1470                      ', g_access_mode=>'||g_access_mode||
1471                      ', g_current_org_id=>'||g_current_org_id||
1472                      ', g_init_access_mode=>'||g_init_access_mode);
1473      END IF;
1474 
1475    End IF;
1476    return 'Y';
1477 
1478 
1479 EXCEPTION
1480    WHEN OTHERS THEN
1481      generic_error('MO_GLOBAL.IS_MO_INIT_DONE', sqlcode, sqlerrm);
1482 END is_mo_init_done;
1483 
1484 -- Name
1485 --    org_security_global function
1486 -- Purpose
1487 --    This is a restricted policy function to support global data -3116.
1488 FUNCTION org_security_global(obj_schema VARCHAR2,
1489                       obj_name   VARCHAR2) RETURN VARCHAR2
1490 IS
1491 l_ci_debug  fnd_profile_option_values.profile_option_value%TYPE := NULL;
1492 BEGIN
1493 
1494   --
1495   --  Returns different predicates based on the access_mode
1496   --  The codes for access_mode are
1497   --  M - Multiple OU Access
1498   --  A - All OU Access
1499   --  S - Single OU Access
1500   --  Null - Backward Compatibility - CLIENT_INFO case
1501   --
1502   --  The Predicates will be appended to Multi-Org synonyms
1503 
1504   IF g_access_mode IS NOT NULL THEN
1505     IF g_access_mode = 'S' THEN
1506        RETURN 'org_id = sys_context(''multi_org2'',''current_org_id'') OR (org_id = -3116)';
1507 
1508     ELSIF g_access_mode = 'M' THEN
1509         RETURN '(EXISTS (SELECT 1
1510                       FROM mo_glob_org_access_tmp oa
1511                       WHERE oa.organization_id = org_id))
1512                  OR (org_id = -3116)';
1513     ELSIF g_access_mode in ('A','B') THEN
1514       RETURN 'org_id <> -3113';           -- Bug5109430 filter seed data from policy predicate
1515     ELSIF g_access_mode = 'X' THEN
1516       RETURN '1 = 2';
1517 
1518     END IF;
1519 
1520   ELSE
1521    --
1522    -- Interim solution for MFG teams
1523    --
1524    fnd_profile.get('FND_MO_INIT_CI_DEBUG', l_ci_debug);
1525    IF l_ci_debug = 'Y' THEN
1526       RETURN 'org_id = substrb(userenv(''CLIENT_INFO''),1,10)';
1527    ELSE
1528       RETURN '1=2';
1529    END IF;
1530 
1531   END IF;
1532 
1533 END org_security_global;
1534 
1535 --
1536 -- Name
1537 --   get_ou_tab
1538 -- Purpose
1539 --   This function returns a table that contains the
1540 --   identifiers of all the accessible operating units.
1541 --
1542 FUNCTION get_ou_tab RETURN OrgIdTab
1543 IS
1544 BEGIN
1545 --  use memory instead of hitting the table
1546 --  select organization_id BULK COLLECT INTO l_ou_id_tab from mo_glob_org_access_tmp;
1547    RETURN g_ou_id_tab;
1548 END get_ou_tab;
1549 
1550 --
1551 -- Name
1552 --   set_policy_context_server
1553 -- Purpose
1554 --   This wrapper is called from Forms client-side library to synchronize
1555 --   current_org_id variable w/ :GLOBAL.current_org_id when set_policy_context
1556 --   API is invoked in Forms.
1557 --
1558 PROCEDURE set_policy_context_server(p_access_mode VARCHAR2,
1559                                     p_org_id      NUMBER)
1560 IS
1561 
1562 BEGIN
1563 
1564   IF (FND_LOG.LEVEL_PROCEDURE >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
1565       FND_LOG.STRING(FND_LOG.LEVEL_PROCEDURE,
1566                      'fnd.plsql.MO_GLOBAL.SET_POLICY_CONTEXT_SERVER.begin',
1567                      'Calling PL/SQL procedure MO_GLOBAL.SET_POLICY_CONTEXT_SERVER:'||
1568                      ' p_access_mode=>'||p_access_mode||
1569                      ',p_org_id=>'||p_org_id);
1570   END IF;
1571 
1572   MO_GLOBAL.set_policy_context(p_access_mode, p_org_id); -- Force server-side to sync
1573 
1574 END set_policy_context_server;
1575 
1576 --
1577 -- Name
1578 --   populate_organizations
1579 -- Purpose
1580 --   This is a wrapper API to populate_orgs called
1581 --   from FND_CONCURRENT API. Not to be used for
1582 --   any other purpose
1583 --
1584 
1585 
1586 Procedure populate_organizations(p_org_id_char     IN         VARCHAR2,
1587                          p_sp_id_char      IN         VARCHAR2,
1588                          p_current_org_id  OUT NOCOPY VARCHAR2,
1589                          p_view_all_org    OUT NOCOPY VARCHAR2)
1590 
1591 IS
1592 BEGIN
1593 
1594 populate_orgs (p_org_id_char,
1595                          p_sp_id_char,
1596                          p_current_org_id,
1597                          p_view_all_org);
1598 END populate_organizations;
1599 
1600 
1601 --
1602 -- Name
1603 --   delete_organizations
1604 -- Purpose
1605 --   This is a wrapper API to delete_orgs called
1606 --   from FND_CONCURRENT API. Not to be used for
1607 --   any other purpose
1608 --
1609 PROCEDURE delete_organizations
1610 IS
1611 BEGIN
1612 delete_orgs;
1613 
1614 END delete_organizations;
1615 
1616 
1617 END mo_global;