DBA Data[Home] [Help]

PACKAGE BODY: APPS.AMW_VIOLATION_PVT

Source


1 PACKAGE BODY AMW_VIOLATION_PVT AS
2 /* $Header: amwvvlab.pls 120.40 2007/09/18 10:58:44 ptulasi ship $ */
3 -- ===============================================================
4 -- Package name
5 --          AMW_VIOLATION_PVT
6 -- Purpose
7 --
8 -- History
9 -- 		  	06/01/2005    tsho     Create
10 -- ===============================================================
11 
12 
13 -- store potential violation info (valid for one constraint)
14 G_ROLE_NAME_LIST            G_VARCHAR2_LONG_TABLE;
15 G_RESPONSIBILITY_ID_LIST    G_NUMBER_TABLE;
16 G_MENU_ID_LIST              G_NUMBER_TABLE;
17 G_FUNCTION_ID_LIST          G_NUMBER_TABLE;
18 G_ENTRY_OBJECT_TYPE_LIST    G_VARCHAR2_CODE_TABLE;
19 G_GROUP_CODE_LIST           G_VARCHAR2_CODE_TABLE;
20 G_PV_COUNT                  NUMBER;
21 
22 --store role/resp hierarchy structure
23 G_ROLE_NAME_LIST_HIER            G_VARCHAR2_LONG_TABLE;
24 G_RESPONSIBILITY_ID_LIST_HIER   G_NUMBER_TABLE;
25 G_MENU_ID_LIST_HIER           G_NUMBER_TABLE;
26 G_FUNCTION_ID_LIST_HIER        G_NUMBER_TABLE;
27 G_ENTRY_OBJECT_TYPE_LIST_HIER    G_VARCHAR2_CODE_TABLE;
28 G_GROUP_CODE_LIST_HIER          G_VARCHAR2_CODE_TABLE;
29 G_PV_COUNT_HIER                NUMBER;
30 
31 
32 G_BULK_COLLECTS_SUPPORTED 	VARCHAR2(30) := 'TRUE';
33 
34 -- copy from FND_FUNCTION.C_MAX_MENU_ENTRIES (AFSCFNSB.pls 115.51 2003/08/01)
35 -- This constant is used for recursion detection in the fallback
36 -- runtime menu scan.  We keep track of how many items are on the menu,
37 -- and assume if the number of entries on the current
38 -- menu is too high then it's caused by recursion.
39 C_MAX_MENU_ENTRIES CONSTANT pls_integer := 10000;
40 
41 
42 -- copy from FND_FUNCTION.P_LAST_RESP_ID (AFSCFNSB.pls 115.51 2003/08/01)
43 -- copy from FND_FUNCTION.P_LAST_RESP_APPL_ID (AFSCFNSB.pls 115.51 2003/08/01)
44 -- copy from FND_FUNCTION.P_LAST_MENU_ID (AFSCFNSB.pls 115.51 2003/08/01)
45 -- This simple cache will avoid the need to find which menu is on
46 -- the current responsibility with SQL every time.  We just store
47 -- the menu around after we get it for the current resp.
48 P_LAST_RESP_ID NUMBER := -1;
49 P_LAST_RESP_APPL_ID NUMBER := -1;
50 P_LAST_MENU_ID NUMBER := -1;
51 
52 -- ===============================================================
53 -- Function name
54 --          Is_ICM_Installed
55 --
56 -- Purpose
57 --          check to see if ICM is installed or not.
58 --          other ICM API should be called only when 'Y' is return from Is_ICM_Installed
59 -- Params
60 --
61 -- Return
62 --          'Y' := ICM is installed
63 --          'N' := ICM is not installed
64 -- History
65 -- 		  	07/19/2005    tsho     Create
66 -- ===============================================================
67 Function Is_ICM_Installed
68 RETURN VARCHAR2
69 IS
70 is_icm_valid    varchar2(1);
71 dummy           varchar2(1);
72 
73 TYPE icmCurTyp IS REF CURSOR;
74 c_has_icm icmCurTyp;
75 l_has_icm_sql varchar2(64) := 'select null from AMW_CONSTRAINTS_B where rownum = 1';
76 
77 BEGIN
78 
79   is_icm_valid := 'N';
80 
81   OPEN c_has_icm FOR l_has_icm_sql;
82   FETCH c_has_icm INTO dummy;
83   IF (c_has_icm%notfound) THEN
84     is_icm_valid := 'N';
85   ELSE
86     is_icm_valid := 'Y';
87   END IF;
88   CLOSE c_has_icm;
89 
90   return is_icm_valid;
91 
92 EXCEPTION
93     WHEN others then
94         return 'N';
95 END Is_ICM_Installed;
96 
97 
98 -- ===============================================================
99 -- Procedure name
100 --          Has_Violations_For_Mode
101 --
102 -- Purpose
103 --          check for OICM SOD constriants that will be violated
104 --          if the user is assigned these additional roles as well as inherited roles
105 --          This Procedure is called from the UMX_REGISTRATION_UTIL.ICM_VIOLATION_CHECK
106 -- Params
107 --          p_user_id            := input fnd user_id
108 --          p_role_names         := input a list of new roles
109 --          p_mode               := input check mode ('ADMIN', 'APPROVE', 'SUBS')
110 --          x_violat_hashtable   := This API will put return parameters in a Associate Table format,
111 --                                  it at least contains the following key/value pairs:
112 --                                  HasViolations      : 'Y' or 'N' to indicate if introducing violations when trying to add those roles to the user
113 --                                  ViolationDetail   : the OAFunc/Region containing violation details for the user , mainly used for Notification.
114 --
115 -- History
116 -- 		  	07/19/2005    tsho     Create
117 -- ===============================================================
118 Procedure Has_Violations_For_Mode (
119     p_user_id               IN  NUMBER,
120     p_role_names            IN  JTF_VARCHAR2_TABLE_400,
121     p_mode                  IN  VARCHAR2,
122     x_violat_hashtable      OUT NOCOPY G_VARCHAR2_HASHTABLE
123 )
124 IS
125     l_violat_region     VARCHAR2(320);
126     l_violat_btn_region VARCHAR2(320);
127     l_has_violation     VARCHAR2(1);
128     l_return_status     VARCHAR2(10);
129     l_msg_count         NUMBER;
130     l_msg_data          VARCHAR2(5000);
131 BEGIN
132   Has_Violations (
133     p_user_id=>p_user_id,
134     p_role_names=>p_role_names,
135     p_mode=>p_mode,
136     x_violat_region=>l_violat_region,
137     x_violat_btn_region=>l_violat_btn_region,
138     x_has_violation=>l_has_violation,
139     x_return_status=>l_return_status,
140     x_msg_count=>l_msg_count,
141     x_msg_data=>l_msg_data);
142 
143     IF (l_has_violation = 'Y') THEN
144 
145         x_violat_hashtable('HasViolations') := 'Y';
146 
147 	  -- 07/13/2006 psomanat : Fix for bug 5388850
148 	  -- ptulasi : 09/03/07
149         -- bug: 6371514 : Modified below code to correct the url
150         x_violat_hashtable('ViolationDetail') := 'AMW_ROLE_APPROVAL_NOTIFY&pNewRoleName='||p_role_names(1)||'&pUserId='||p_user_id;
151         --x_violat_hashtable('ViolationDetail') := 'AMW_ROLE_APPROVAL_NOTIFY='||p_role_names(1)||'='||p_user_id;
152         --x_violat_hashtable('ViolationDetail') := 'AMW_ROLE_APPROVAL_NOTIFY=--=--';
153     ELSE
154         x_violat_hashtable('HasViolations') := 'N';
155         x_violat_hashtable('ViolationDetail') := NULL;
156     END IF;
157 
158 END Has_Violations_For_Mode;
159 
160 -- ===============================================================
161 -- Procedure name
162 --          Has_Violations
163 -- This procedure is obsolated due to bug 5407266
164 -- ===============================================================
165 Procedure Has_Violations (
166     p_user_id               IN  NUMBER,
167     p_role_names            IN  JTF_VARCHAR2_TABLE_400,
168     p_mode                  IN  VARCHAR2,
169     x_violat_region         OUT NOCOPY VARCHAR2,
170     x_violat_btn_region     OUT NOCOPY VARCHAR2,
171     x_has_violation         OUT NOCOPY VARCHAR2,
172     x_return_status         OUT NOCOPY VARCHAR2,
173     x_msg_count             OUT NOCOPY NUMBER,
174     x_msg_data              OUT NOCOPY VARCHAR2
175 )
176 IS
177 
178 L_API_NAME                  CONSTANT VARCHAR2(30) := 'Has_Violations';
179 L_API_VERSION_NUMBER        CONSTANT NUMBER		  := 1.0;
180 
181 l_new_resp_name VARCHAR2(320);
182 l_existing_resp_name VARCHAR2(320);
183 
184 
185 BEGIN
186 
187  Has_Violations (
188     p_user_id=>p_user_id,
189     p_role_names=>p_role_names,
190     p_revoked_role_names   => NULL,
191     p_mode  => p_mode,
192     x_violat_region => x_violat_region,
193     x_violat_btn_region => x_violat_btn_region,
194     x_has_violation => x_has_violation,
195     x_new_resp_name  => l_new_resp_name,
196     x_existing_resp_name => l_existing_resp_name,
197     x_return_status => x_return_status,
198     x_msg_count => x_msg_count,
199     x_msg_data => x_msg_data);
200 
201 END Has_Violations;
202 
203 
204 -- ===============================================================
205 -- Procedure name
206 --          Has_Violations
207 --
208 -- Purpose
209 --          check for OICM SOD constriants that will be violated
210 --          if the user is assigned these additional roles as well as inherited roles
211 -- Params
212 --          p_user_id            := input fnd user_id
213 --          p_role_names         := input a list of new roles
214 --          p_revoked_role_names  := input a list of revoked roles
215 --          p_mode               := input check mode ('ADMIN', 'APPROVE', 'SUBS')
216 --          x_violat_region      := output full path dialog region name to display potential violation detials.
217 --                                  (ie. /oracle/apps/amw/audit/duty/webui/....RN)
218 --          x_violat_btn_region  := output full path dialog button region name to display page level buttons.
219 --                                  (ie. /oracle/apps/amw/audit/duty/webui/....RN)
220 --                                  this button region is different depending on the override privilege of Administrator
221 --          x_has_violation      := output 'Y' if this user will have violations with the new roles assigned; output 'N' otherwise.
222 --
223 --          x_new_resp_name      := output a list of newly assigned resps/roles which violate the sod
224 --          x_existing_resp_name := output a list of existing resps/roles which violate the sod
225 -- History
226 -- 		  	06/01/2005    tsho     Create
227 --          08/03/2005    tsho     Consider User Waivers
228 --          04/28/2006    dliao	   Consider RESPALL/RESPME/RESPSET
229 -- ===============================================================
230 Procedure Has_Violations (
231     p_user_id               IN  NUMBER,
232     p_role_names            IN  JTF_VARCHAR2_TABLE_400,
233     p_revoked_role_names    IN  JTF_VARCHAR2_TABLE_400,
234     p_mode                  IN  VARCHAR2,
235     x_violat_region         OUT NOCOPY VARCHAR2,
236     x_violat_btn_region     OUT NOCOPY VARCHAR2,
237     x_has_violation         OUT NOCOPY VARCHAR2,
238     x_new_resp_name         OUT NOCOPY VARCHAR2,
239     x_existing_resp_name    OUT NOCOPY VARCHAR2,
240     x_return_status         OUT NOCOPY VARCHAR2,
241     x_msg_count             OUT NOCOPY NUMBER,
242     x_msg_data              OUT NOCOPY VARCHAR2
243 )
244 IS
245 
246 L_API_NAME                  CONSTANT VARCHAR2(30) := 'Has_Violations';
247 L_API_VERSION_NUMBER        CONSTANT NUMBER		  := 1.0;
248 
249 
250 -- find all valid constraints
251 CURSOR c_all_valid_constraints IS
252       SELECT constraint_rev_id, type_code
253       FROM amw_constraints_b
254       WHERE start_date <= sysdate AND (end_date IS NULL OR end_date >= sysdate)
255       AND objective_code = 'PR';
256 l_all_valid_constraints c_all_valid_constraints%ROWTYPE;
257 
258 -- find the number of constraint entries(incompatible functions) by specified constraint_rev_id
259 l_constraint_entries_count NUMBER;
260 l_func_access_count NUMBER;
261 l_group_access_count NUMBER;
262 l_resp_access_count NUMBER;
263 
264 
265 CURSOR c_constraint_entries_count (l_constraint_rev_id IN NUMBER) IS
266       SELECT count(*)
267       FROM amw_constraint_entries
268       WHERE constraint_rev_id = l_constraint_rev_id;
269 
270 TYPE refCurTyp IS REF CURSOR;
271 func_acess_count_c refCurTyp;
272 group_acess_count_c refCurTyp;
273 new_violation_count_c refCurTyp;
274 resp_acess_count_c refCurTyp;
275 violating_new_resps_c refCurTyp;
276 violating_old_resps_c refCurTyp;
277 existing_violation_c refCurTyp;
278 
279 -- store passed-in p_role_names, p_revoked_role_names as string, sperated by ','
280 l_role_names VARCHAR2(32767);
281 l_sub_role_names VARCHAR2(32767);
282 l_revoked_role_names VARCHAR2(32767);
283 
284 l_func_dynamic_sql   VARCHAR2(32767);
285 l_vio_exist_role_sql VARCHAR2(32767);
286 l_vio_exist_resp_sql VARCHAR2(32767);
287 
288 l_func_sql VARCHAR2(32767);
289 l_func_existing_sql   VARCHAR2(32767);
290 
291 
292 l_func_set_dynamic_sql   VARCHAR2(32767);
293 l_func_set_existing_sql   VARCHAR2(32767);
294 
295 l_resp_sql VARCHAR2(32767);
296 l_resp_dynamic_sql  VARCHAR2(32767);
297 l_resp_existing_sql   VARCHAR2(32767);
298 
299 l_resp_set_dynamic_sql   VARCHAR2(32767);
300 l_resp_set_existing_sql   VARCHAR2(32767);
301 
302 
303 
304 -- get valid user waiver
305 l_valid_user_waiver_count NUMBER;
306 CURSOR c_valid_user_waivers (l_constraint_rev_id IN NUMBER, l_user_id IN NUMBER) IS
307     SELECT count(*)
308       FROM amw_constraint_waivers_vl
309      WHERE constraint_rev_id = l_constraint_rev_id
310        AND object_type = 'USER'
311        AND PK1 = l_user_id
312        AND start_date <= sysdate AND (end_date >= sysdate or end_date is null);
313 
314 -- get violated responsibilities
315 CURSOR c_violated_responsibilities(l_constraint_rev_id IN NUMBER) IS
316 	SELECT resp.responsibility_name
317 	  FROM fnd_responsibility_vl resp
318 	WHERE resp.responsibility_id in (
319 		SELECT function_id
320 		FROM amw_constraint_entries cons
321 		WHERE constraint_rev_id = l_constraint_rev_id
322 		AND cons.application_id = resp.application_id);
323 
324 l_cst_new_violation_sql   VARCHAR2(5000) ;
325 l_sub_revoked_role_names    VARCHAR2(32767);
326 
327 
328 l_violating_new_roles_sql varchar2(32767);
329 l_violating_new_resp_table JTF_VARCHAR2_TABLE_400;
330 l_violating_existing_roles_sql VARCHAR2(32767);
331 l_violating_old_resp_table JTF_VARCHAR2_TABLE_400;
332 
333 l_existing_violation_sql varchar2(32676);
334 l_new_violation_table JTF_VARCHAR2_TABLE_400;
335 l_existing_violation_table JTF_VARCHAR2_TABLE_400;
336 
337 
338 BEGIN
339   l_role_names := NULL;
340   l_revoked_role_names := NULL;
341   x_violat_region := NULL;
342   x_violat_btn_region := NULL;
343   l_valid_user_waiver_count := 0;
344 
345   -- default to 'N', which means user doesn't have violations
346   x_has_violation := 'N';
347 
348   IF (p_revoked_role_names IS NULL or p_revoked_role_names.FIRST IS NULL or p_revoked_role_names(1) IS NULL
349     or p_revoked_role_names(1) = '' ) THEN
350 	  l_sub_revoked_role_names := '';
351   ELSE
352   	-- store pass-in p_revoked_role_names as flat string
353     l_revoked_role_names := ''''||p_revoked_role_names(1) || '''';
354     FOR i IN 2 .. p_revoked_role_names.COUNT
355     LOOP
356       l_revoked_role_names := l_revoked_role_names||',''' ||p_revoked_role_names(i) || '''';
357     END LOOP;
358 
359     l_sub_revoked_role_names := ' and uar.role_name not in ( ' ||
360           ' select  distinct ROLE_NAME  from wf_user_role_assignments_v a '||
361           ' where a.assigning_role IN ( ' || l_revoked_role_names || ' ) '||
362           ' AND a.role_name = a.assigning_role  ) ';
363 
364           /*** add the inherited roles
365           ' UNION ALL  '||
366           ' select distinct ROLE_NAME  from wf_user_role_assignments_v b  '||
367           ' where user_name = (select user_name from fnd_user where user_id = ' || p_user_id  || ' ) '||
368           ' and b.assigning_role IN ( ' || l_revoked_role_names || ' ) '||
369           ' and b.role_name <> b.assigning_role  '||
370           ' and b.start_date <= sysdate and (b.end_date is null or b.end_date > sysdate)  '||
371           ' and b.role_name not in  '||
372           ' (SELECT c.ROLE_NAME FROM wf_user_role_assignments_v c WHERE  '||
373           ' c.start_date <= sysdate and (c.end_date is null or c.end_date > sysdate)  '||
374           ' and c.ASSIGNING_ROLE IN (  '||
375           ' select ROLE_NAME from wf_user_role_assignments_v d  '||
376           ' where d.role_name = d.assigning_role  '||
377           ' and d.role_name not in (' || l_revoked_role_names || ' ) '||
378           ' and d.start_date <= sysdate and (d.end_date is null or d.end_date > sysdate))))';
379           *************/
380 
381  END IF;
382 
383  l_func_existing_sql :=
384     '  select rcd.function_id '
385   ||'  from amw_role_constraint_denorm rcd '
386   ||'      ,'||G_AMW_USER_ROLES||' ur '
387   ||'      ,'||G_AMW_user||' u '
388   ||'      ,'||G_AMW_USER_ROLE_ASSIGNMENTS_V || ' uar '
389   ||'  where rcd.constraint_rev_id = :1 '
390   ||'    and u.user_id = :2 '
391   ||'    and u.user_name = ur.user_name '
392   ||'    and uar.user_name = ur.user_name '
393   ||'    and uar.role_name = ur.role_name '
394   ||'    and uar.start_date <= sysdate '
395   ||'    and (uar.end_date is null or uar.end_date >= sysdate) '
396   ||'    and ( (ur.role_name = rcd.role_name '
397   ||'    and ur.role_orig_system = ''UMX'' ) '
398   ||'    or ( ur.role_orig_system_id = rcd.responsibility_id '
399   ||'    and ur.role_orig_system = ''FND_RESP'' ) ) '
400   ||     l_sub_revoked_role_names
401   ||'  UNION ALL '
402   ||'  select rcd.function_id '
403   ||'  from amw_role_constraint_denorm rcd '
404   ||'      ,'||G_AMW_GRANTS||' gra '
405   ||'  where rcd.constraint_rev_id = :3 '
406   ||'    and gra.instance_type = ''GLOBAL'' and gra.menu_id = rcd.menu_id '
407   ||'    and gra.object_id = -1 and ( gra.grantee_type = ''GLOBAL'' '
408   ||'    or ( gra.grantee_type = ''USER'' and gra.grantee_key = (select u.user_name from '
409   ||    G_AMW_USER || ' u where u.user_id = :4 ))) ';
410 
411 
412 l_func_set_existing_sql :=
413     '  select rcd.group_code '
414   ||'  from amw_role_constraint_denorm rcd '
415   ||'      ,'||G_AMW_USER_ROLES||' ur '
416   ||'      ,'||G_AMW_user||' u '
417   ||'      ,'||G_AMW_USER_ROLE_ASSIGNMENTS_V || ' uar '
418   ||'  where rcd.constraint_rev_id = :1 '
419   ||'    and u.user_id = :2 '
420   ||'    and u.user_name = ur.user_name '
421   ||'    and uar.user_name = ur.user_name '
422   ||'    and uar.role_name = ur.role_name '
423   ||'    and uar.start_date <= sysdate '
424   ||'    and (uar.end_date is null or uar.end_date >= sysdate) '
425   ||'    and ( (ur.role_name = rcd.role_name '
426   ||'    and ur.role_orig_system = ''UMX'' ) '
427   ||'    or ( ur.role_orig_system_id = rcd.responsibility_id '
428   ||'    and ur.role_orig_system = ''FND_RESP'' ) ) '
429   ||     l_sub_revoked_role_names
430   ||'  UNION ALL '
431   ||'  select rcd.group_code '
432   ||'  from amw_role_constraint_denorm rcd '
433   ||'      ,'||G_AMW_GRANTS||' gra '
434   ||'  where rcd.constraint_rev_id = :3 '
435   ||'    and gra.instance_type = ''GLOBAL'' and gra.menu_id = rcd.menu_id '
436   ||'    and gra.object_id = -1 and ( gra.grantee_type = ''GLOBAL'' '
437   ||'    or ( gra.grantee_type = ''USER'' and gra.grantee_key = (select u.user_name from '
438   ||    G_AMW_USER || ' u where u.user_id = :4 ))) ';
439 
440 l_resp_existing_sql :=
441   '  select ur.role_orig_system_id '
442   ||'  from '
443   || G_AMW_USER_ROLES||' ur '
444   ||'      ,'||G_AMW_user||' u '
445   ||'      ,amw_constraint_entries cst '
446   ||'      ,'||G_AMW_USER_ROLE_ASSIGNMENTS_V || ' uar '
447   ||'  where  u.user_id = :1 '
448   ||'    and  cst.constraint_rev_id = :2 '
449   ||'    and u.user_name = ur.user_name '
450   ||'    and ur.role_orig_system_id = cst.function_id '
451   ||'    and ur.role_orig_system = ''FND_RESP'' '
452   ||'    and uar.user_name = ur.user_name '
453   ||'    and uar.role_name = ur.role_name '
454   ||'    and uar.start_date <= sysdate '
455   ||'    and (uar.end_date is null or uar.end_date >= sysdate) '
456   ||     l_sub_revoked_role_names ;
457 
458 l_resp_set_existing_sql :=
459   '  select cst.group_code '
460   ||'  from '
461   || G_AMW_USER_ROLES||' ur '
462   ||'      ,'||G_AMW_user||' u '
463   ||'      ,amw_constraint_entries cst '
464   ||'      ,'||G_AMW_USER_ROLE_ASSIGNMENTS_V || ' uar '
465   ||'  where  u.user_id = :1 '
466   ||'    and  cst.constraint_rev_id = :2 '
467   ||'    and u.user_name = ur.user_name '
468   ||'    and ur.role_orig_system_id = cst.function_id '
469   ||'    and ur.role_orig_system = ''FND_RESP'' '
470   ||'    and uar.user_name = ur.user_name '
471   ||'    and uar.role_name = ur.role_name '
472   ||'    and uar.start_date <= sysdate '
473   ||'    and (uar.end_date is null or uar.end_date >= sysdate) '
474   ||     l_sub_revoked_role_names;
475 
476 
477   IF (p_user_id IS NOT NULL AND p_role_names IS NOT NULL AND p_role_names.FIRST IS NOT NULL) THEN
478 
479     -- store pass-in p_role_names as flat string
480     l_role_names := ''''||p_role_names(1)||'''';
481     FOR i IN 2 .. p_role_names.COUNT
482     LOOP
483       l_role_names := l_role_names||','''||p_role_names(i)||'''';
484     END LOOP;
485 
486     l_sub_role_names :=
487          ' SELECT distinct SUPER_NAME '||
488          ' FROM              WF_ROLE_HIERARCHIES '||
489          ' WHERE ENABLED_FLAG = ''Y''  '||
490          ' CONNECT BY PRIOR  SUPER_NAME = SUB_NAME  '||
491          ' AND  PRIOR        ENABLED_FLAG = ''Y''  '||
492          ' START WITH        SUB_NAME in (  '|| l_role_names || ' ) ' ||
493          ' union all '||
494          ' SELECT NAME '||
495          ' FROM WF_ROLES '||
496          ' WHERE NAME IN (  '|| l_role_names || ' ) ';
497 
498 
499     -- check all valid constraints
500     OPEN c_all_valid_constraints;
501     LOOP
502      FETCH c_all_valid_constraints INTO l_all_valid_constraints;
503      EXIT WHEN c_all_valid_constraints%NOTFOUND;
504 
505      -- check if this user is waived (due to User Waiver) from this constraint
506      OPEN c_valid_user_waivers(l_all_valid_constraints.constraint_rev_id, p_user_id);
507      FETCH c_valid_user_waivers INTO l_valid_user_waiver_count;
508      CLOSE c_valid_user_waivers;
509 
510      IF l_valid_user_waiver_count <= 0 THEN
511 
512       l_func_dynamic_sql :=
513           'select count(distinct function_id) from ( '
514         ||   l_func_existing_sql
515         ||'  UNION ALL '
516         ||'  select rcd.function_id '
517         ||'  from amw_role_constraint_denorm rcd '
518         ||'  where rcd.constraint_rev_id = :5 '
519         ||'    and rcd.role_name in ( '||l_sub_role_names||' ) '
520         ||') ';
521 
522       l_func_set_dynamic_sql :=
523           'select count(distinct group_code) from ( '
524         ||   l_func_set_existing_sql
525         ||'  UNION ALL '
526         ||'  select rcd.group_code '
527         ||'  from amw_role_constraint_denorm rcd '
528         ||'  where rcd.constraint_rev_id = :5 '
529         ||'    and rcd.role_name in ( '||l_sub_role_names||' ) '
530         ||') ';
531 
532         l_resp_dynamic_sql  :=
533          'select count(distinct role_orig_system_id) from ( '
534         ||   l_resp_existing_sql
535         ||'  UNION ALL '
536         ||'  select distinct rle.orig_system_id '
537         ||'  from  ' || G_AMW_ALL_ROLES_VL || ' rle '
538         ||'  , amw_constraint_entries cst '
539         ||'  where rle.orig_system = ''FND_RESP'' '
540         ||'  and cst.constraint_rev_id = :3 '
541         ||'  and cst.function_id = rle.orig_system_id '
542         ||'  and rle.name in ( '||l_sub_role_names||' ) '
543         ||') ';
544 
545          l_resp_set_dynamic_sql :=
546           'select count(distinct group_code) from ( '
547         ||   l_resp_set_existing_sql
548         ||'  UNION ALL '
549         ||'  select cst.group_code '
550         ||'  from  ' || G_AMW_ALL_ROLES_VL || ' rle '
551         ||'  , amw_constraint_entries cst '
552         ||'  where rle.orig_system = ''FND_RESP'' '
553         ||'  and cst.constraint_rev_id = :3 '
554         ||'  and cst.function_id = rle.orig_system_id '
555         ||'  and rle.name in ( '||l_sub_role_names||' ) '
556         ||') ';
557 
558         l_violating_new_roles_sql :=
559         'select resp.responsibility_name from fnd_responsibility_vl resp'
560         ||' where resp.responsibility_id in ( '
561 	||' select function_id from amw_constraint_entries cons, wf_roles rl '
562 	||' where constraint_rev_id = :1 '
563         ||' and cons.application_id = resp.application_id '
564 	||' and cons.function_id = rl.orig_system_id '
565         ||' and rl.orig_system = ''FND_RESP'' '
566         ||' and rl.name in (' ||l_sub_role_names||' ) '
567         ||' and rl.owner_tag = (select application_short_name '
568 	||' from fnd_application app where app.application_id = resp.application_id)) ';
569 
570         l_violating_existing_roles_sql :=
571         'select resp.responsibility_name from fnd_responsibility_vl resp'
572         ||' where resp.responsibility_id in ( '
573 	||' select function_id from amw_constraint_entries cons, wf_roles rl '
574 	||' where constraint_rev_id = :1 '
575         ||' and cons.application_id = resp.application_id '
576 	||' and cons.function_id = rl.orig_system_id '
577         ||' and rl.orig_system = ''FND_RESP'' '
578         ||' and rl.name not in (' ||l_sub_role_names||' ) '
579         ||' and rl.owner_tag = (select application_short_name '
580 	||' from fnd_application app where app.application_id = resp.application_id)) ';
581 
582 
583       IF 'ALL' = l_all_valid_constraints.type_code THEN
584         -- find the number of constraint entries(incompatible functions) by specified constraint_rev_id
585         OPEN c_constraint_entries_count (l_all_valid_constraints.constraint_rev_id);
586         FETCH c_constraint_entries_count INTO l_constraint_entries_count;
587         CLOSE c_constraint_entries_count;
588 
589         -- 12:16:05 : psomanat
590         -- Check to see if violation is due to the allready
591         -- assigned violating roles
592 
593         -- 5:15:06 by dliao remove because we need check if the new assigned roles violate the constraint
594         -- even if the allready assigned violating roles exist.
595         /***
596         l_vio_exist_role_sql :='select count(distinct function_id)'
597             ||'from ('
598             ||' select function_id from amw_constraint_entries where constraint_rev_id = :1'
599             ||' MINUS '
600             ||'select distinct function_id from ( '
601             ||   l_func_existing_sql
602             ||') '
603             ||')';
604          ***/
605 
606          --add 5:15:06 by dliao
607          --check the new roles
608         l_cst_new_violation_sql :=
609                 '  select count(rcd.function_id) '
610                 ||' from amw_role_constraint_denorm rcd '
611                 ||'  where rcd.constraint_rev_id = :1 '
612                 ||'    and rcd.role_name in ( '||l_sub_role_names||' ) ' ;
613 
614 
615         OPEN func_acess_count_c FOR l_cst_new_violation_sql USING
616             l_all_valid_constraints.constraint_rev_id;
617         FETCH func_acess_count_c INTO l_func_access_count;
618         CLOSE func_acess_count_c;
619 
620         -- If the count is 0 then the violation is due to the allready
621         -- assigned violating role.
622         IF l_func_access_count > 0 THEN
623 
624             OPEN func_acess_count_c FOR l_func_dynamic_sql USING
625             l_all_valid_constraints.constraint_rev_id,
626             p_user_id,
627             l_all_valid_constraints.constraint_rev_id,
628             p_user_id,
629             l_all_valid_constraints.constraint_rev_id;
630             FETCH func_acess_count_c INTO l_func_access_count;
631             CLOSE func_acess_count_c;
632 
633             -- in ALL type: if user can access to all entries of this constraint,
634             -- he violates this constraint
635             IF l_func_access_count = l_constraint_entries_count THEN
636 
637 
638 
639             -- Check to see if the fuction enteries in the constraint is same
640             -- as the functions the user can access due to the assigning of
641             -- this role
642             l_func_sql :='select count(distinct function_id)'
643                     ||'from ('
644                     ||'select distinct function_id from ( '
645                     ||   l_func_existing_sql
646                     ||'  UNION ALL '
647                     ||'  select rcd.function_id '
648                     ||'  from amw_role_constraint_denorm rcd '
649                     ||'  where rcd.constraint_rev_id = :5 '
650                     ||'  and rcd.role_name in ( '||l_sub_role_names||' ) '
651                     ||') '
652                     ||' MINUS '
653                     ||' select FUNCTION_ID from amw_constraint_entries where constraint_rev_id = :6'
654                     ||')';
655 
656 
657                 OPEN func_acess_count_c FOR l_func_sql USING
658                 l_all_valid_constraints.constraint_rev_id,
659                 p_user_id,
660                 l_all_valid_constraints.constraint_rev_id,
661                 p_user_id,
662                 l_all_valid_constraints.constraint_rev_id,
663                 l_all_valid_constraints.constraint_rev_id;
664                 FETCH func_acess_count_c INTO l_func_access_count;
665                 CLOSE func_acess_count_c;
666 
667                 IF l_func_access_count = 0 THEN
668                  -- once he violates at least one constraint, break the loop and inform FALSE to the caller
669                     FND_FILE.put_line(fnd_file.log, '----fail on constraint - ALL = '||l_all_valid_constraints.constraint_rev_id ||' ---------------');
670                     x_has_violation := 'Y';
671                     EXIT;
672                 END IF;
673             END IF;
674         END IF;
675       ELSIF 'ME' = l_all_valid_constraints.type_code THEN
676 
677         -- 12:16:2005 : psomanat
678         -- Check to see if violation is due to the allready
679         -- assigned violating roles
680         -- 5:15:06 by dliao remove because we need check if the new assigned roles violate the constraint
681         -- even if the allready assigned violating roles exist.
682         /********************************************************
683         l_vio_exist_role_sql :='select count(distinct function_id) from ( '
684             ||   l_func_existing_sql
685             ||')';
686 
687          OPEN func_acess_count_c FOR l_vio_exist_role_sql USING
688           l_all_valid_constraints.constraint_rev_id,
689           p_user_id,
690           l_all_valid_constraints.constraint_rev_id,
691           p_user_id,
692           l_all_valid_constraints.constraint_rev_id,
693           p_user_id,
694           l_all_valid_constraints.constraint_rev_id;
695         FETCH func_acess_count_c INTO l_func_access_count;
696         CLOSE func_acess_count_c;
697         ****************************************************/
698 
699         --PSOMANAT :23:01:2006
700         -- scenario added : The user allready violates a constraint and again
701         -- a new violating role is added
702 
703         --DLIAO 05:12:2006
704         -- remove this condition because l_func_access_count will be 0 if the existing
705         -- roles which the user was assigned don't violate any constraint.
706         -- IF l_func_access_count >= 1 THEN
707 
708 
709             l_cst_new_violation_sql :=
710                 '  select count(rcd.function_id) '
711                 ||' from amw_role_constraint_denorm rcd '
712                 ||'  where rcd.constraint_rev_id = :1 '
713                 ||'    and rcd.role_name in ( '||l_sub_role_names||' ) ' ;
714 
715 
716             -- The cursor checks if the current constraint violation is related
717             -- role being added to the user.
718             -- This is done to avoid the following problem :
719             --      The user may allready have roles violating a differnt constraint
720             -- then the one under process. If we don't check to see if the role
721             -- assigned is related with the current constraint, there is a possibility
722             -- of reporting the existing violation again and again even thought they are
723             -- allready assigned.
724 
725             OPEN new_violation_count_c FOR l_cst_new_violation_sql USING
726                 l_all_valid_constraints.constraint_rev_id;
727             FETCH new_violation_count_c INTO l_func_access_count;
728             CLOSE new_violation_count_c;
729 
730             -- If the function count is > 0 then the violation is due to
731             -- the current constraint.
732             -- If not then the violation is due to some other constraint.
733             -- So we need to continue to find the correct constraint
734             IF l_func_access_count > 0 THEN
735 
736                -- find the number of distinct constraint entries this user can access
737                 OPEN func_acess_count_c FOR l_func_dynamic_sql USING
738                     l_all_valid_constraints.constraint_rev_id,
739                     p_user_id,
740                     l_all_valid_constraints.constraint_rev_id,
741                     p_user_id,
742                     l_all_valid_constraints.constraint_rev_id;
743                 FETCH func_acess_count_c INTO l_func_access_count;
744                 CLOSE func_acess_count_c;
745 
746                 -- in ME type: if user can access at least two entries of this constraint,
747                 -- he violates this constraint
748                 IF l_func_access_count >= 2 THEN
749                     -- once he violates at least one constraint, break the loop and inform FALSE to the caller
750                     FND_FILE.put_line(fnd_file.log,'------------ fail on constraint - ME = '||l_all_valid_constraints.constraint_rev_id ||' ---------------');
751                     x_has_violation := 'Y';
752                     exit;
753                 END IF;
754             END IF;
755 
756       ELSIF 'SET' = l_all_valid_constraints.type_code THEN
757         -- 12:16:2005 : psomanat
758         -- Check to see if violation is due to the allready
759         -- assigned violating roles
760         -- 5:15:06 by dliao remove because we need check if the new assigned roles violate the constraint
761         -- even if the allready assigned violating roles exist.
762         /******************************************
763         l_vio_exist_role_sql :='select count(distinct group_code) from ( '
764             ||  l_func_set_existing_sql
765             ||  ') ';
766         OPEN group_acess_count_c FOR l_vio_exist_role_sql USING
767           l_all_valid_constraints.constraint_rev_id,
768           p_user_id,
769           l_all_valid_constraints.constraint_rev_id,
770           p_user_id,
771           l_all_valid_constraints.constraint_rev_id,
772           p_user_id,
773           l_all_valid_constraints.constraint_rev_id;
774         FETCH group_acess_count_c INTO l_group_access_count;
775         CLOSE group_acess_count_c;
776         *********************************************/
777 
778         -- PSOMANAT :23:01:2006
779         -- scenario added : The user allready violates a constraint and again
780         -- a new violating role is added
781          --DLIAO 05:12:2006
782         -- remove this condition because l_func_access_count will be 0 if the existing
783         -- roles which the user was assigned don't violate any constraint.
784 
785         --IF l_group_access_count >= 1 THEN
786 
787             l_cst_new_violation_sql :=
788                 '  select count( distinct rcd.group_code) '
789                 ||' from amw_role_constraint_denorm rcd '
790                 ||'  where rcd.constraint_rev_id = :1 '
791                 ||'    and rcd.role_name in ( '||l_sub_role_names||' ) ' ;
792 
793             -- The cursor checks if the current constraint violation is related
794             -- role being added to the user.
795             -- This is done to avoid the following problem :
796             --      The user may allready have roles violating a differnt constraint
797             -- then the one under process. If we don't check to see if the role
798             -- assigned is related with the current constraint, there is a possibility
799             -- of reporting the existing violation again and again even thought they are
800             -- allready assigned.
801 
802             OPEN new_violation_count_c FOR l_cst_new_violation_sql USING
803                 l_all_valid_constraints.constraint_rev_id;
804             FETCH new_violation_count_c INTO l_group_access_count;
805             CLOSE new_violation_count_c;
806 
807             -- If the group access count is > 0 then the violation is due to
808             -- the current constraint.
809             -- If not then the violation is due to some other constraint.
810             -- So we need to continue to find the correct constraint
811             IF l_group_access_count > 0 THEN
812                 -- find the number of distinct constraint entries this user can access
813                 OPEN group_acess_count_c FOR l_func_set_dynamic_sql USING
814                     l_all_valid_constraints.constraint_rev_id,
815                     p_user_id,
816                     l_all_valid_constraints.constraint_rev_id,
817                     p_user_id,
818                     l_all_valid_constraints.constraint_rev_id;
819                 FETCH group_acess_count_c INTO l_group_access_count;
820                 CLOSE group_acess_count_c;
821 
822 
823                 -- in SET type: if user can access at least two distinct groups(set) of this constraint,
824                 -- he violates this constraint
825                 IF l_group_access_count >= 2 THEN
826                     -- once he violates at least one constraint, break the loop and inform FALSE to the caller
827                     FND_FILE.put_line(fnd_file.log,'------------ fail on constraint - SET = '||l_all_valid_constraints.constraint_rev_id ||' ---------------');
828                     x_has_violation := 'Y';
829                 END IF;
830             END IF;
831 
832         ELSIF 'RESPALL' = l_all_valid_constraints.type_code THEN
833 
834         -- find the number of constraint entries(incompatible functions) by specified constraint_rev_id
835         OPEN c_constraint_entries_count (l_all_valid_constraints.constraint_rev_id);
836         FETCH c_constraint_entries_count INTO l_constraint_entries_count;
837         CLOSE c_constraint_entries_count;
838 
839         -- Check to see if violation is due to the allready
840         -- assigned violating roles
841         l_vio_exist_resp_sql :='select count(distinct function_id)'
842             ||'from ('
843             ||' select function_id from amw_constraint_entries where constraint_rev_id = :1'
844             ||' MINUS '
845             ||'select distinct role_orig_system_id from ( '
846             ||   l_resp_existing_sql
847             ||') '
848             ||')';
849 
850         OPEN resp_acess_count_c FOR l_vio_exist_resp_sql USING
851             l_all_valid_constraints.constraint_rev_id,
852             p_user_id,
853             l_all_valid_constraints.constraint_rev_id;
854         FETCH resp_acess_count_c INTO l_resp_access_count;
855         CLOSE resp_acess_count_c;
856 
857 
858         -- If the count is 0 then the violation is due to the allready
859         -- assigned violating role.
860         IF l_resp_access_count <> 0 THEN
861 
862             OPEN resp_acess_count_c FOR l_resp_dynamic_sql USING
863             p_user_id,
864             l_all_valid_constraints.constraint_rev_id,
865             l_all_valid_constraints.constraint_rev_id;
866             FETCH resp_acess_count_c INTO l_resp_access_count;
867             CLOSE resp_acess_count_c;
868 
869             -- in ALL type: if user can access to all entries of this constraint,
870             -- he violates this constraint
871             IF l_resp_access_count = l_constraint_entries_count THEN
872 
873             -- Check to see if the fuction enteries in the constraint is same
874             -- as the functions the user can access due to the assigning of
875             -- this role
876 
877             l_resp_sql := 'select count(distinct role_orig_system_id)'
878              ||' from ('
879              ||   l_resp_existing_sql
880              ||'  UNION ALL '
881              ||'  select distinct rle.orig_system_id  as role_orig_system_id '
882              ||'  from  ' || G_AMW_ALL_ROLES_VL || ' rle '
883              ||'  , amw_constraint_entries cst '
884              ||'  where rle.orig_system = ''FND_RESP'' '
885              ||'  and cst.constraint_rev_id = :3 '
886              ||'  and cst.function_id = rle.orig_system_id '
887              ||'  and rle.name in ( '||l_sub_role_names||' ) '
888              ||' MINUS '
889              ||' select FUNCTION_ID from amw_constraint_entries where constraint_rev_id = :4'
890              ||')';
891 
892 
893 
894                 OPEN resp_acess_count_c FOR l_resp_sql USING
895                 p_user_id,
896                 l_all_valid_constraints.constraint_rev_id,
897                 l_all_valid_constraints.constraint_rev_id,
898                 l_all_valid_constraints.constraint_rev_id;
899                 FETCH resp_acess_count_c INTO l_resp_access_count;
900                 CLOSE resp_acess_count_c;
901 
902                 IF l_resp_access_count = 0 THEN
903                  -- once he violates at least one constraint, break the loop and inform FALSE to the caller
904                     FND_FILE.put_line(fnd_file.log, '----fail on constraint - ALL = '||l_all_valid_constraints.constraint_rev_id ||' ---------------');
905                     x_has_violation := 'Y';
906 
907                  OPEN violating_new_resps_c FOR l_violating_new_roles_sql USING
908                  l_all_valid_constraints.constraint_rev_id;
909 		 FETCH violating_new_resps_c BULK COLLECT INTO l_violating_new_resp_table;
910     		 CLOSE violating_new_resps_c;
911 
912     		 OPEN violating_old_resps_c FOR l_violating_existing_roles_sql USING
913                  l_all_valid_constraints.constraint_rev_id;
914 		 FETCH violating_old_resps_c BULK COLLECT INTO l_violating_old_resp_table;
915     		 CLOSE violating_old_resps_c;
916 
917     		  IF l_violating_new_resp_table IS NOT NULL AND l_violating_new_resp_table.FIRST IS NOT NULL THEN
918     		 	x_new_resp_name := l_violating_new_resp_table(1);
919       			FOR i in 2 .. l_violating_new_resp_table.COUNT
920       			LOOP
921         		   x_new_resp_name := x_new_resp_name ||','|| l_violating_new_resp_table(i);
922       			END LOOP;
923     		END IF; -- end of if: l_violating_new_resp_table IS NOT NULL
924 
925     		 IF l_violating_old_resp_table IS NOT NULL AND l_violating_old_resp_table.FIRST IS NOT NULL THEN
926     		 	x_existing_resp_name := '''' || l_violating_old_resp_table(1);
927       			FOR j in 2 .. l_violating_old_resp_table.COUNT
928       			LOOP
929       			 x_existing_resp_name := x_existing_resp_name ||','|| l_violating_old_resp_table(j);
930       			END LOOP;
931       			x_existing_resp_name := x_existing_resp_name || '''';
932     		END IF; -- end of if: l_violating_old_resp_table IS NOT NULL
933 
934                     EXIT;
935                 END IF;
936             END IF;
937         END IF;
938 
939         ELSIF 'RESPME' = l_all_valid_constraints.type_code THEN
940 
941         -- Check to see if violation is due to the allready
942         -- assigned violating roles
943        /*********************
944         l_vio_exist_resp_sql :='select count(distinct role_orig_system_id)'
945             ||'from ('
946             ||   l_resp_existing_sql
947             ||')';
948 
949         OPEN resp_acess_count_c FOR l_vio_exist_resp_sql USING
950             p_user_id,
951             l_all_valid_constraints.constraint_rev_id;
952         FETCH resp_acess_count_c INTO l_resp_access_count;
953         CLOSE resp_acess_count_c;
954 
955         *********************/
956 
957         -- scenario added : The user allready violates a constraint and again
958         -- a new violating role is added
959         -- remove this condition because l_resp_access_count will be 0 if the existing
960         -- roles which the user is assigned don't violate any constraint.
961        -- IF l_resp_access_count >= 1 THEN
962 
963 
964             l_cst_new_violation_sql :=
965              '  select distinct rle.display_name '
966              ||'  from  ' || G_AMW_ALL_ROLES_VL || ' rle '
967              ||'  , amw_constraint_entries cst '
968              ||'  where rle.orig_system = ''FND_RESP'' '
969              ||'  and cst.constraint_rev_id = :1 '
970              ||'  and cst.function_id = rle.orig_system_id '
971              ||'  and rle.name in ( '||l_sub_role_names||' ) '
972              ||'  and rle.owner_tag = (select application_short_name '
973              ||'  from fnd_application app where app.application_id = cst.application_id)';
974 
975 
976             -- The cursor checks if the current constraint violation is related
977             -- role being added to the user.
978             -- This is done to avoid the following problem :
979             --      The user may allready have roles violating a differnt constraint
980             -- then the one under process. If we don't check to see if the role
981             -- assigned is related with the current constraint, there is a possibility
982             -- of reporting the existing violation again and again even thought they are
983             -- allready assigned.
984 
985             OPEN new_violation_count_c FOR l_cst_new_violation_sql USING
986                 l_all_valid_constraints.constraint_rev_id;
987             FETCH new_violation_count_c BULK COLLECT INTO l_new_violation_table;
988             CLOSE new_violation_count_c;
989 
990             l_existing_violation_sql :=
991                '  select distinct rle.display_name '
992                ||'  from '
993                || G_AMW_USER_ROLES||' ur '
994                ||'      ,'||G_AMW_user||' u '
995                ||'      ,amw_constraint_entries cst '
996                ||'      ,'||G_AMW_USER_ROLE_ASSIGNMENTS_V || ' uar '
997                ||'      ,'||G_AMW_ALL_ROLES_VL || ' rle '
998                ||'  where  u.user_id = :1 '
999                ||'    and  cst.constraint_rev_id = :2 '
1000                ||'    and u.user_name = ur.user_name '
1001                ||'    and ur.role_orig_system_id = cst.function_id '
1002                ||'    and ur.role_orig_system = ''FND_RESP'' '
1003                ||'    and ur.role_orig_system = rle.orig_system '
1004                ||'    and ur.role_orig_system_id = rle.orig_system_id '
1005                ||'    and ur.role_name = rle.name '
1006                ||'    and rle.owner_tag = (select application_short_name '
1007                ||'    from fnd_application app where app.application_id = cst.application_id) '
1008                ||'    and uar.user_name = ur.user_name '
1009                ||'    and uar.role_name = ur.role_name '
1010                ||'    and uar.start_date <= sysdate '
1011                ||'    and (uar.end_date is null or uar.end_date >= sysdate) '
1012                ||     l_sub_revoked_role_names ;
1013 
1014 
1015 
1016             OPEN existing_violation_c FOR l_existing_violation_sql USING
1017                 p_user_id,
1018                 l_all_valid_constraints.constraint_rev_id;
1019             FETCH existing_violation_c BULK COLLECT INTO l_existing_violation_table;
1020             CLOSE existing_violation_c;
1021 
1022             -- If the function count is > 0 then the violation is due to
1023             -- the current constraint.
1024             -- If not then the violation is due to some other constraint.
1025             -- So we need to continue to find the correct constraint
1026             -- in ME type: if user can access at least two entries of this constraint,
1027             -- he violates this constraint
1028 
1029             IF ( l_new_violation_table.COUNT > 0) AND (l_existing_violation_table.COUNT +  l_new_violation_table.COUNT >= 2) THEN
1030 
1031             -- Check to see if the fuction enteries in the constraint is same
1032             -- as the functions the user can access due to the assigning of
1033             -- this role
1034 
1035             l_resp_sql := 'select count(distinct role_orig_system_id)'
1036              ||' from ('
1037              ||   l_resp_existing_sql
1038              ||'  UNION ALL '
1039              ||'  select distinct rle.orig_system_id  as role_orig_system_id '
1040              ||'  from  ' || G_AMW_ALL_ROLES_VL || ' rle '
1041              ||'  , amw_constraint_entries cst '
1042              ||'  where rle.orig_system = ''FND_RESP'' '
1043              ||'  and cst.constraint_rev_id = :3 '
1044              ||'  and cst.function_id = rle.orig_system_id '
1045              ||'  and rle.name in ( '||l_sub_role_names||' ) '
1046              ||'  and rle.owner_tag = (select application_short_name '
1047              ||'  from fnd_application app where app.application_id = cst.application_id)'
1048              ||' MINUS '
1049              ||' select FUNCTION_ID from amw_constraint_entries where constraint_rev_id = :4'
1050              ||')';
1051 
1052 
1053                 -- find the number of distinct constraint entries this user can access
1054 
1055                 OPEN resp_acess_count_c FOR l_resp_sql USING
1056                 p_user_id,
1057                 l_all_valid_constraints.constraint_rev_id,
1058                 l_all_valid_constraints.constraint_rev_id,
1059                 l_all_valid_constraints.constraint_rev_id;
1060                 FETCH resp_acess_count_c INTO l_resp_access_count;
1061                 CLOSE resp_acess_count_c;
1062 
1063 
1064 
1065                 IF l_resp_access_count = 0 THEN
1066                     -- once he violates at least one constraint, break the loop and inform FALSE to the caller
1067                     FND_FILE.put_line(fnd_file.log,'------------ fail on constraint - ME = '||l_all_valid_constraints.constraint_rev_id ||' ---------------');
1068                     x_has_violation := 'Y';
1069 
1070                      IF l_new_violation_table IS NOT NULL AND l_new_violation_table.FIRST IS NOT NULL THEN
1071     		 	x_new_resp_name := l_new_violation_table(1);
1072       			FOR i in 2 .. l_new_violation_table.COUNT
1073       			LOOP
1074         		   x_new_resp_name := x_new_resp_name ||','|| l_new_violation_table(i);
1075       			END LOOP;
1076     		   END IF; -- end of if: l_new_violation_table IS NOT NULL
1077 
1078     		 IF l_existing_violation_table IS NOT NULL AND l_existing_violation_table.FIRST IS NOT NULL THEN
1079     		 	x_existing_resp_name := '''' || l_existing_violation_table(1);
1080       			FOR j in 2 .. l_existing_violation_table.COUNT
1081       			LOOP
1082         		  x_existing_resp_name := x_existing_resp_name ||','|| l_existing_violation_table(j);
1083       			END LOOP;
1084       			x_existing_resp_name := x_existing_resp_name || '''';
1085     		END IF; -- end of if: l_existing_violation_table IS NOT NULL
1086 
1087                     exit;
1088                 END IF;
1089             END IF;
1090         --END IF;
1091 
1092       ELSIF 'RESPSET' = l_all_valid_constraints.type_code THEN
1093 
1094         -- Check to see if violation is due to the allready
1095         -- assigned violating roles
1096         -- 5:15:06 by dliao remove because we need check if the new assigned roles violate the constraint
1097         -- even if the allready assigned violating roles exist.
1098         /***********************************************
1099         l_vio_exist_resp_sql :='select count(distinct role_orig_system_id)'
1100             ||'from ('
1101             ||'select distinct role_orig_system_id from ( '
1102             ||   l_resp_existing_sql
1103             ||') '
1104             ||')';
1105 
1106 
1107         OPEN group_acess_count_c FOR l_vio_exist_resp_sql USING
1108           p_user_id,
1109           l_all_valid_constraints.constraint_rev_id;
1110         FETCH group_acess_count_c INTO l_group_access_count;
1111         CLOSE group_acess_count_c;
1112 
1113         *****************************************************/
1114 
1115         -- scenario added : The user allready violates a constraint and again
1116         -- a new violating role is added
1117 	--IF l_group_access_count >= 1 THEN
1118 
1119 	l_cst_new_violation_sql :=
1120              '  select distinct rle.display_name '
1121              ||'  from  ' || G_AMW_ALL_ROLES_VL || ' rle '
1122              ||'  , amw_constraint_entries cst '
1123              ||'  where rle.orig_system = ''FND_RESP'' '
1124              ||'  and cst.constraint_rev_id = :1 '
1125              ||'  and cst.function_id = rle.orig_system_id '
1126              ||'  and rle.name in ( '||l_sub_role_names||' ) '
1127              ||'  and rle.owner_tag = (select application_short_name '
1128              ||'  from fnd_application app where app.application_id = cst.application_id)';
1129 
1130             -- The cursor checks if the current constraint violation is related
1131             -- role being added to the user.
1132             -- This is done to avoid the following problem :
1133             --      The user may allready have roles violating a differnt constraint
1134             -- then the one under process. If we don't check to see if the role
1135             -- assigned is related with the current constraint, there is a possibility
1136             -- of reporting the existing violation again and again even thought they are
1137             -- allready assigned.
1138 
1139 
1140             OPEN new_violation_count_c FOR l_cst_new_violation_sql USING
1141                 l_all_valid_constraints.constraint_rev_id;
1142             FETCH new_violation_count_c BULK COLLECT INTO l_new_violation_table;
1143             CLOSE new_violation_count_c;
1144 
1145 	   l_existing_violation_sql :=
1146                '  select distinct rle.display_name '
1147                ||'  from '
1148                || G_AMW_USER_ROLES||' ur '
1149                ||'      ,'||G_AMW_user||' u '
1150                ||'      ,amw_constraint_entries cst '
1151                ||'      ,'||G_AMW_USER_ROLE_ASSIGNMENTS_V || ' uar '
1152                ||'      ,'||G_AMW_ALL_ROLES_VL || ' rle '
1153                ||'  where  u.user_id = :1 '
1154                ||'    and  cst.constraint_rev_id = :2 '
1155                ||'    and u.user_name = ur.user_name '
1156                ||'    and ur.role_orig_system_id = cst.function_id '
1157                ||'    and ur.role_orig_system = ''FND_RESP'' '
1158                ||'    and ur.role_orig_system = rle.orig_system '
1159                ||'    and ur.role_orig_system_id = rle.orig_system_id '
1160                ||'    and ur.role_name = rle.name '
1161                ||'    and rle.owner_tag = (select application_short_name '
1162                ||'    from fnd_application app where app.application_id = cst.application_id) '
1163                ||'    and uar.user_name = ur.user_name '
1164                ||'    and uar.role_name = ur.role_name '
1165                ||'    and uar.start_date <= sysdate '
1166                ||'    and (uar.end_date is null or uar.end_date >= sysdate) '
1167                ||     l_sub_revoked_role_names ;
1168 
1169 
1170 
1171             OPEN existing_violation_c FOR l_existing_violation_sql USING
1172                 p_user_id,
1173                 l_all_valid_constraints.constraint_rev_id;
1174             FETCH existing_violation_c BULK COLLECT INTO l_existing_violation_table;
1175             CLOSE existing_violation_c;
1176 
1177 
1178 
1179 
1180 
1181             -- If the function count is > 0 then the violation is due to
1182             -- the current constraint.
1183             -- If not then the violation is due to some other constraint.
1184             -- So we need to continue to find the correct constraint
1185             IF l_new_violation_table.COUNT > 0 THEN
1186 
1187               -- find the number of distinct constraint entries this user can access
1188 
1189                 OPEN resp_acess_count_c FOR l_resp_set_dynamic_sql USING
1190                 p_user_id,
1191                 l_all_valid_constraints.constraint_rev_id,
1192                 l_all_valid_constraints.constraint_rev_id;
1193                 FETCH resp_acess_count_c INTO l_resp_access_count;
1194                 CLOSE resp_acess_count_c;
1195 
1196                 -- in SET type: if user can access at least two distinct groups(set) of this constraint,
1197                 -- he violates this constraint
1198                 IF l_resp_access_count >= 2 THEN
1199                     -- once he violates at least one constraint, break the loop and inform FALSE to the caller
1200                     FND_FILE.put_line(fnd_file.log,'------------ fail on constraint - SET = '||l_all_valid_constraints.constraint_rev_id ||' ---------------');
1201                     x_has_violation := 'Y';
1202 
1203 
1204                      IF l_new_violation_table IS NOT NULL AND l_new_violation_table.FIRST IS NOT NULL THEN
1205     		 	x_new_resp_name := l_new_violation_table(1);
1206       			FOR i in 2 .. l_new_violation_table.COUNT
1207       			LOOP
1208         		   x_new_resp_name := x_new_resp_name ||','|| l_new_violation_table(i);
1209       			END LOOP;
1210     		   END IF; -- end of if: l_new_violation_table IS NOT NULL
1211 
1212     		 IF l_existing_violation_table IS NOT NULL AND l_existing_violation_table.FIRST IS NOT NULL THEN
1213     		 	x_existing_resp_name := '''' || l_existing_violation_table(1);
1214       			FOR j in 2 .. l_existing_violation_table.COUNT
1215       			LOOP
1216         		   x_existing_resp_name := x_existing_resp_name ||','|| l_existing_violation_table(j);
1217       			END LOOP;
1218       			x_existing_resp_name := x_existing_resp_name || '''';
1219     		END IF; -- end of if: l_existing_violation_table IS NOT NULL
1220 
1221 
1222                     EXIT;
1223                 END IF;
1224             END IF;
1225       ELSE
1226         -- other constraint types
1227         NULL;
1228       END IF; -- end of if: constraint type_code
1229      END IF; -- end of if: l_valid_user_waiver_count <= 0
1230     END LOOP; --end of loop: c_all_valid_constraints
1231     CLOSE c_all_valid_constraints;
1232 
1233   END IF; -- end of if: p_user_id IS NOT NULL AND p_responsibility_id IS NOT NULL AND p_role_names IS NOT NULL AND p_role_names.FIRST IS NOT NULL
1234   -- only output valid region name if having violation; otherwise, NULL
1235 
1236   IF x_has_violation = 'Y' THEN
1237     x_violat_region := '/oracle/apps/amw/audit/duty/webui/RoleAssignViolationRN';
1238     x_violat_btn_region := '/oracle/apps/amw/audit/duty/webui/RoleAssignViolationOverrideBtnRN';
1239   END IF;
1240 exception
1241     when others then
1242             dbms_output.put_line('exception');
1243 END Has_Violations;
1244 
1245 
1246 
1247 -- ===============================================================
1248 -- Function name
1249 --          Has_Violation_Due_To_Resp
1250 --
1251 -- Purpose
1252 --          check for OICM SOD constriants that will be violated
1253 --          if the user is assigned the additional responsibility
1254 -- Params
1255 --          p_user_id            := input fnd user_id
1256 --          p_responsibility_id  := input fnd responsibility_id
1257 -- Return
1258 --          'N'                  := if no SOD violation found.
1259 --          'Y'                  := if SOD violation exists.
1260 --                                  The SOD violation should NOT be restricted to
1261 --                                  only the new responsiblity.
1262 --                                  If the existing responsibilities have any violations,
1263 --                                  the function should return 'Y' as well.
1264 --
1265 -- History
1266 -- 		  	07/13/2005    tsho     Create
1267 --          08/03/2005    tsho     Consider User Waivers
1268 --          08/22/2005    tsho     Consider only prevent(PR) constraint objective
1269 -- ===============================================================
1270 Function Has_Violation_Due_To_Resp (
1271     p_user_id               IN  NUMBER,
1272     p_responsibility_id     IN  NUMBER
1273 ) return VARCHAR2
1274 IS
1275 L_API_NAME                  CONSTANT VARCHAR2(30) := 'Has_Violation_Due_To_Resp';
1276 L_API_VERSION_NUMBER        CONSTANT NUMBER		  := 1.0;
1277 
1278 -- return result
1279 has_violation VARCHAR2(32767);
1280 
1281 -- find all valid constraints
1282 CURSOR c_all_valid_constraints IS
1283       SELECT constraint_rev_id, type_code, objective_code
1284         FROM amw_constraints_b
1285        WHERE start_date <= sysdate AND (end_date IS NULL OR end_date >= sysdate);
1286 l_all_valid_constraints c_all_valid_constraints%ROWTYPE;
1287 
1288 -- find the number of constraint entries(incompatible functions) by specified constraint_rev_id
1289 l_constraint_entries_count NUMBER;
1290 l_func_access_count NUMBER;
1291 l_group_access_count NUMBER;
1292 CURSOR c_constraint_entries_count (l_constraint_rev_id IN NUMBER) IS
1293       SELECT count(*)
1294         FROM amw_constraint_entries
1295 	   WHERE constraint_rev_id=l_constraint_rev_id;
1296 
1297 TYPE refCurTyp IS REF CURSOR;
1298 func_acess_count_c refCurTyp;
1299 group_acess_count_c refCurTyp;
1300 
1301 l_func_dynamic_sql   VARCHAR2(2500)  :=
1302     'select count(distinct function_id) from ( '
1303   ||'  select rcd.function_id '
1304   ||'  from amw_role_constraint_denorm rcd '
1305   ||'      ,'||G_AMW_USER_ROLES||' ur '
1306   ||'      ,'||G_AMW_user||' u '
1307   ||'  where rcd.constraint_rev_id = :1 '
1308   ||'    and u.user_id = :2 '
1309   ||'    and u.user_name = ur.user_name '
1310   ||'    and ur.role_name = rcd.role_name '
1311   ||'    and ur.role_orig_system = ''UMX'' '
1312   ||'  UNION ALL '
1313   ||'  select rcd.function_id '
1314   ||'  from amw_role_constraint_denorm rcd '
1315   ||'      ,'||G_AMW_USER_ROLES||' ur '
1316   ||'      ,'||G_AMW_user||' u '
1317   ||'  where rcd.constraint_rev_id = :3 '
1318   ||'    and u.user_id = :4 '
1319   ||'    and u.user_name = ur.user_name '
1320   ||'    and ur.role_orig_system_id = rcd.responsibility_id '
1321   ||'    and ur.role_orig_system = ''FND_RESP'' '
1322   ||'  UNION ALL '
1323   ||'  select rcd.function_id '
1324   ||'  from amw_role_constraint_denorm rcd '
1325   ||'      ,'||G_AMW_GRANTS||' gra '
1326   ||'      ,'||G_AMW_USER||' u '
1327   ||'  where rcd.constraint_rev_id = :5 '
1328   ||'    and u.user_id = :6 '
1329   ||'    and u.user_name = gra.grantee_key '
1330   ||'    and gra.grantee_type = ''USER'' '
1331   ||'    and gra.menu_id = rcd.menu_id '
1332   ||'    and gra.instance_type = ''GLOBAL'' '
1333   ||'    and gra.object_id = -1 '
1334   ||'  UNION ALL '
1335   ||'  select rcd.function_id '
1336   ||'  from amw_role_constraint_denorm rcd '
1337   ||'      ,'||G_AMW_GRANTS||' gra '
1338   ||'  where rcd.constraint_rev_id = :7 '
1339   ||'    and gra.grantee_key = ''GLOBAL'' '
1340   ||'    and gra.grantee_type = ''GLOBAL'' '
1341   ||'    and gra.menu_id = rcd.menu_id '
1342   ||'    and gra.instance_type = ''GLOBAL'' '
1343   ||'    and gra.object_id = -1 '
1344   ||'  UNION ALL '
1345   ||'  select rcd.function_id '
1346   ||'  from amw_role_constraint_denorm rcd '
1347   ||'  where rcd.constraint_rev_id = :8 '
1348   ||'    and rcd.responsibility_id = :9 '
1349   ||') ';
1350 
1351 l_func_set_dynamic_sql   VARCHAR2(2500)  :=
1352     'select count(distinct group_code) from ( '
1353   ||'  select rcd.group_code '
1354   ||'  from amw_role_constraint_denorm rcd '
1355   ||'      ,'||G_AMW_USER_ROLES||' ur '
1356   ||'      ,'||G_AMW_user||' u '
1357   ||'  where rcd.constraint_rev_id = :1 '
1358   ||'    and u.user_id = :2 '
1359   ||'    and u.user_name = ur.user_name '
1360   ||'    and ur.role_name = rcd.role_name '
1361   ||'    and ur.role_orig_system = ''UMX'' '
1362   ||'  UNION ALL '
1363   ||'  select rcd.group_code '
1364   ||'  from amw_role_constraint_denorm rcd '
1365   ||'      ,'||G_AMW_USER_ROLES||' ur '
1366   ||'      ,'||G_AMW_user||' u '
1367   ||'  where rcd.constraint_rev_id = :3 '
1368   ||'    and u.user_id = :4 '
1369   ||'    and u.user_name = ur.user_name '
1370   ||'    and ur.role_orig_system_id = rcd.responsibility_id '
1371   ||'    and ur.role_orig_system = ''FND_RESP'' '
1372   ||'  UNION ALL '
1373   ||'  select rcd.group_code '
1374   ||'  from amw_role_constraint_denorm rcd '
1375   ||'      ,'||G_AMW_GRANTS||' gra '
1376   ||'      ,'||G_AMW_USER||' u '
1377   ||'  where rcd.constraint_rev_id = :5 '
1378   ||'    and u.user_id = :6 '
1379   ||'    and u.user_name = gra.grantee_key '
1380   ||'    and gra.grantee_type = ''USER'' '
1381   ||'    and gra.menu_id = rcd.menu_id '
1382   ||'    and gra.instance_type = ''GLOBAL'' '
1383   ||'    and gra.object_id = -1 '
1384   ||'  UNION ALL '
1385   ||'  select rcd.group_code '
1386   ||'  from amw_role_constraint_denorm rcd '
1387   ||'      ,'||G_AMW_GRANTS||' gra '
1388   ||'  where rcd.constraint_rev_id = :7 '
1389   ||'    and gra.grantee_key = ''GLOBAL'' '
1390   ||'    and gra.grantee_type = ''GLOBAL'' '
1391   ||'    and gra.menu_id = rcd.menu_id '
1392   ||'    and gra.instance_type = ''GLOBAL'' '
1393   ||'    and gra.object_id = -1 '
1394   ||'  UNION ALL '
1395   ||'  select rcd.group_code '
1396   ||'  from amw_role_constraint_denorm rcd '
1397   ||'  where rcd.constraint_rev_id = :8 '
1398   ||'    and rcd.responsibility_id = :9 '
1399   ||') ';
1400 
1401 -- get valid user waiver
1402 l_valid_user_waiver_count NUMBER;
1403 CURSOR c_valid_user_waivers (l_constraint_rev_id IN NUMBER, l_user_id IN NUMBER) IS
1404     SELECT count(*)
1405       FROM amw_constraint_waivers
1406      WHERE constraint_rev_id = l_constraint_rev_id
1407        AND object_type = 'USER'
1408        AND PK1 = l_user_id
1409        AND start_date <= sysdate AND (end_date >= sysdate or end_date is null);
1410 
1411 BEGIN
1412   -- default to 'N', which means user doesn't have violations
1413   has_violation := 'N';
1414   l_valid_user_waiver_count := 0;
1415 
1416   IF (p_user_id IS NOT NULL AND p_responsibility_id IS NOT NULL) THEN
1417     -- check all valid constraints
1418     OPEN c_all_valid_constraints;
1419     LOOP
1420      FETCH c_all_valid_constraints INTO l_all_valid_constraints;
1421      EXIT WHEN c_all_valid_constraints%NOTFOUND;
1422 
1423      -- check if this user is waived (due to User Waiver) from this constraint
1424      OPEN c_valid_user_waivers(l_all_valid_constraints.constraint_rev_id, p_user_id);
1425      FETCH c_valid_user_waivers INTO l_valid_user_waiver_count;
1426      CLOSE c_valid_user_waivers;
1427 
1428      -- 08.22.2005 tsho: consider only Prevent Constraint Objective
1429 	 -- IF l_valid_user_waiver_count <= 0 THEN
1430 	 IF l_valid_user_waiver_count <= 0 AND l_all_valid_constraints.objective_code = 'PR' THEN
1431 
1432       IF 'ALL' = l_all_valid_constraints.type_code THEN
1433         -- find the number of constraint entries(incompatible functions) by specified constraint_rev_id
1434         OPEN c_constraint_entries_count (l_all_valid_constraints.constraint_rev_id);
1435         FETCH c_constraint_entries_count INTO l_constraint_entries_count;
1436         CLOSE c_constraint_entries_count;
1437 
1438         -- find the number of distinct constraint entries this user can access
1439         OPEN func_acess_count_c FOR l_func_dynamic_sql USING
1440           l_all_valid_constraints.constraint_rev_id,
1441           p_user_id,
1442           l_all_valid_constraints.constraint_rev_id,
1443           p_user_id,
1444           l_all_valid_constraints.constraint_rev_id,
1445           p_user_id,
1446           l_all_valid_constraints.constraint_rev_id,
1447           l_all_valid_constraints.constraint_rev_id,
1448           p_responsibility_id;
1449         FETCH func_acess_count_c INTO l_func_access_count;
1450         CLOSE func_acess_count_c;
1451 
1452         -- in ALL type: if user can access to all entries of this constraint,
1453         -- he violates this constraint
1454         IF l_func_access_count = l_constraint_entries_count THEN
1455           -- once he violates at least one constraint, break the loop and inform FALSE to the caller
1456           FND_FILE.put_line(fnd_file.log, '------------ fail on constraint - ALL = '||l_all_valid_constraints.constraint_rev_id ||' ---------------');
1457           has_violation := 'Y';
1458           return has_violation;
1459         END IF;
1460 
1461       ELSIF 'ME' = l_all_valid_constraints.type_code THEN
1462         -- find the number of distinct constraint entries this user can access
1463         OPEN func_acess_count_c FOR l_func_dynamic_sql USING
1464           l_all_valid_constraints.constraint_rev_id,
1465           p_user_id,
1466           l_all_valid_constraints.constraint_rev_id,
1467           p_user_id,
1468           l_all_valid_constraints.constraint_rev_id,
1469           p_user_id,
1470           l_all_valid_constraints.constraint_rev_id,
1471           l_all_valid_constraints.constraint_rev_id,
1472           p_responsibility_id;
1473         FETCH func_acess_count_c INTO l_func_access_count;
1474         CLOSE func_acess_count_c;
1475 
1476         -- in ME type: if user can access at least two entries of this constraint,
1477         -- he violates this constraint
1478         IF l_func_access_count >= 2 THEN
1479           -- once he violates at least one constraint, break the loop and inform FALSE to the caller
1480           FND_FILE.put_line(fnd_file.log,'------------ fail on constraint - ME = '||l_all_valid_constraints.constraint_rev_id ||' ---------------');
1481           has_violation := 'Y';
1482           return has_violation;
1483         END IF;
1484 
1485       ELSIF 'SET' = l_all_valid_constraints.type_code THEN
1486         -- find the number of distinct constraint entries this user can access
1487         OPEN group_acess_count_c FOR l_func_set_dynamic_sql USING
1488           l_all_valid_constraints.constraint_rev_id,
1489           p_user_id,
1490           l_all_valid_constraints.constraint_rev_id,
1491           p_user_id,
1492           l_all_valid_constraints.constraint_rev_id,
1493           p_user_id,
1494           l_all_valid_constraints.constraint_rev_id,
1495           l_all_valid_constraints.constraint_rev_id,
1496           p_responsibility_id;
1497         FETCH group_acess_count_c INTO l_group_access_count;
1498         CLOSE group_acess_count_c;
1499 
1500         -- in SET type: if user can access at least two distinct groups(set) of this constraint,
1501         -- he violates this constraint
1502         IF l_group_access_count >= 2 THEN
1503           -- once he violates at least one constraint, break the loop and inform FALSE to the caller
1504           FND_FILE.put_line(fnd_file.log,'------------ fail on constraint - SET = '||l_all_valid_constraints.constraint_rev_id ||' ---------------');
1505           has_violation := 'Y';
1506           return has_violation;
1507         END IF;
1508       ELSE
1509         -- other constraint types
1510         NULL;
1511       END IF; -- end of if: constraint type_code
1512 
1513      END IF; -- end of if: l_valid_user_waiver_count <= 0
1514 
1515     END LOOP; --end of loop: c_all_valid_constraints
1516     CLOSE c_all_valid_constraints;
1517 
1518   END IF; -- end of if: p_user_id IS NOT NULL AND p_responsibility_id IS NOT NULL
1519 
1520   return has_violation;
1521 
1522 END Has_Violation_Due_To_Resp;
1523 
1524 
1525 
1526 -- ===============================================================
1527 -- Private Procedure name
1528 --          Clear_List
1529 --
1530 -- Purpose
1531 --          to clear the global list:
1532 --              G_FUNCTION_ID_LIST
1533 --              G_MENU_ID_LIST
1534 --              G_RESPONSIBILITY_ID_LIST
1535 --              G_ROLE_NAME_LIST
1536 --              G_ENTRY_OBJECT_TYPE_LIST
1537 --              G_GROUP_CODE_LIST
1538 --
1539 -- ===============================================================
1540 PROCEDURE Clear_List
1541 IS
1542 
1543 L_API_NAME                  CONSTANT VARCHAR2(30) := 'Clear_List';
1544 L_API_VERSION_NUMBER        CONSTANT NUMBER		  := 1.0;
1545 
1546 BEGIN
1547     --FND_FILE.put_line(fnd_file.log,'inside api '||L_API_NAME);
1548     G_ROLE_NAME_LIST.DELETE();
1549     G_RESPONSIBILITY_ID_LIST.DELETE();
1550     G_MENU_ID_LIST.DELETE();
1551     G_FUNCTION_ID_LIST.DELETE();
1552     G_ENTRY_OBJECT_TYPE_LIST.DELETE();
1553     G_GROUP_CODE_LIST.DELETE();
1554     G_PV_COUNT  := 1;
1555 
1556     G_ROLE_NAME_LIST_HIER.DELETE();
1557     G_RESPONSIBILITY_ID_LIST_HIER.DELETE();
1558     G_MENU_ID_LIST_HIER.DELETE();
1559     G_FUNCTION_ID_LIST_HIER.DELETE();
1560     G_ENTRY_OBJECT_TYPE_LIST_HIER.DELETE();
1561     G_GROUP_CODE_LIST_HIER.DELETE();
1562     G_PV_COUNT_HIER  := 1;
1563 
1564 
1565 END Clear_List;
1566 
1567 
1568 -- ===============================================================
1569 -- Private Function name
1570 --          PROCESS_MENU_TREE_DOWN_FOR_MN
1571 --
1572 -- Purpose
1573 --          Plow through the menu tree, processing exclusions and figuring
1574 --          out which functions are accessible.
1575 --
1576 --          This routine processes the menu hierarchy and exclusion rules in PL/SQL
1577 --          rather than in the database.
1578 --          The basic algorithm of this routine is:
1579 --          Populate the list of exclusions by selecting from FND_RESP_FUNCTIONS
1580 --          menulist(1) = p_menu_id
1581 --          while (elements on menulist)
1582 --          {
1583 --              Remove first element off menulist
1584 --              if this menu is not excluded with a menu exclusion rule
1585 --              {
1586 --                  Query all menu entry children of current menu
1587 --                  for (each child) loop
1588 --                  {
1589 --                      If it's excluded by a func exclusion rule, go on to the next one.
1590 --                      If we've got the function we're looking for,
1591 --                        and grant_flag = Y, we're done- return TRUE;
1592 --                      If it's got a sub_menu_id, add it to the end of menulist
1593 --                        to be processed
1594 --                  }
1595 --                  Move to next element on menulist
1596 --              }
1597 --          }
1598 --
1599 -- Params
1600 --          p_menu_id           := menu_id
1601 --          p_function_id       := function to check for
1602 --
1603 --          Don't pass values for the following two params if you don't want
1604 --          exclusions processed.
1605 --          p_appl_id           := application id of resp
1606 --          p_resp_id           := responsibility id
1607 --
1608 --          p_access_given_date := start_date of user resp  (added for AMW)
1609 --          p_access_given_by   := created_by of user resp  (added for AMW)
1610 --
1611 -- Return
1612 --          True    := function accessible
1613 --          False   := function not accessible
1614 --
1615 -- Notes
1616 --          copy from FND_FUNCTION.PROCESS_MENU_TREE_DOWN_FOR_MN (AFSCFNSB.pls 115.51 2003/08/01)
1617 --          and modify for AMW to use dynamic sql
1618 --
1619 --          12.21.2004 tsho: set default NULL for p_access_given_date, p_access_given_by
1620 --          12.21.2004 tsho: fix for performance bug 4036679
1621 -- History
1622 --          05.24.2005 tsho: AMW.E Incompatible Sets,
1623 --          need to pass in amw_constraint_entries.group_code for each item
1624 -- ===============================================================
1625 FUNCTION PROCESS_MENU_TREE_DOWN_FOR_MN(
1626   p_menu_id     in number,
1627   p_function_id in number,
1628   p_appl_id     in number,
1629   p_resp_id     in number,
1630   p_role_name   in varchar2 := NULL,
1631   p_entry_object_type_list  in varchar2 := NULL,
1632   p_group_code              in varchar2 := NULL
1633 ) RETURN boolean
1634 IS
1635 
1636   L_API_NAME                  CONSTANT VARCHAR2(30) := 'PROCESS_MENU_TREE_DOWN_FOR_MN';
1637   L_API_VERSION_NUMBER        CONSTANT NUMBER		  := 1.0;
1638 
1639   l_sub_menu_id number;
1640 
1641   /* Table to store the list of submenus that we are looking for */
1642   TYPE MENULIST_TYPE is table of NUMBER INDEX BY BINARY_INTEGER;
1643   MENULIST  MENULIST_TYPE;
1644 
1645   TYPE NUMBER_TABLE_TYPE is table of NUMBER INDEX BY BINARY_INTEGER;
1646   TYPE VARCHAR2_TABLE_TYPE is table of VARCHAR2(1) INDEX BY BINARY_INTEGER;
1647 
1648   /* The table of exclusions.  The index in is the action_id, and the */
1649   /* value stored in each element is the rule_type.*/
1650   EXCLUSIONS VARCHAR2_TABLE_TYPE;
1651 
1652   /* Returns from the bulk collect (fetches) */
1653   TBL_MENU_ID NUMBER_TABLE_TYPE;
1654   TBL_ENT_SEQ NUMBER_TABLE_TYPE;
1655   TBL_FUNC_ID NUMBER_TABLE_TYPE;
1656   TBL_SUBMNU_ID NUMBER_TABLE_TYPE;
1657   TBL_GNT_FLG VARCHAR2_TABLE_TYPE;
1658 
1659   /* Cursor to get exclusions */
1660   TYPE exclCurTyp IS REF CURSOR;
1661   excl_c exclCurTyp;
1662   l_excl_rule_type     VARCHAR2(30);
1663   l_excl_action_id     NUMBER;
1664   l_excl_dynamic_sql   VARCHAR2(200)  :=
1665         'SELECT RULE_TYPE, ACTION_ID '
1666       ||'  FROM '||G_AMW_RESP_FUNCTIONS
1667       ||' WHERE application_id = :1 '
1668       ||'   AND responsibility_id = :2 ';
1669 
1670   /* Cursor to get menu entries on a particular menu.*/
1671   TYPE mnesCurTyp IS REF CURSOR;
1672   get_mnes_c mnesCurTyp;
1673   l_mnes_menu_id        NUMBER;
1674   l_mnes_entry_sequence NUMBER;
1675   l_mnes_function_id    NUMBER;
1676   l_mnes_sub_menu_id    NUMBER;
1677   l_mnes_grant_flag     VARCHAR2(1);
1678   l_mnes_dynamic_sql   VARCHAR2(200)  :=
1679         'SELECT MENU_ID, ENTRY_SEQUENCE, FUNCTION_ID, SUB_MENU_ID, GRANT_FLAG '
1680       ||'  FROM '||G_AMW_MENU_ENTRIES
1681       ||' WHERE menu_id  = :1 ';
1682 
1683   menulist_cur pls_integer;
1684   menulist_size pls_integer;
1685 
1686   entry_excluded boolean;
1687   last_index pls_integer;
1688   i number;
1689   z number;
1690 
1691 BEGIN
1692   --FND_FILE.put_line(fnd_file.log,'inside api '||L_API_NAME);
1693 
1694   if(p_appl_id is not NULL) then
1695     /* Select the list of exclusion rules into our cache */
1696     OPEN excl_c FOR l_excl_dynamic_sql USING
1697         p_appl_id,
1698         p_resp_id;
1699     LOOP
1700         FETCH excl_c INTO l_excl_rule_type, l_excl_action_id;
1701         EXIT WHEN excl_c%NOTFOUND;
1702         EXCLUSIONS(l_excl_action_id) := l_excl_rule_type;
1703     END LOOP;
1704     CLOSE excl_c;
1705 
1706   end if;
1707 
1708   -- Initialize menulist working list to parent menu
1709   menulist_cur := 0;
1710   menulist_size := 1;
1711   menulist(0) := p_menu_id;
1712 
1713   -- Continue processing until reach the end of list
1714   while (menulist_cur < menulist_size) loop
1715     -- Check if recursion limit exceeded
1716     if (menulist_cur > C_MAX_MENU_ENTRIES) then
1717       /* If the function were accessible from this menu, then we should */
1718       /* have found it before getting to this point, so we are confident */
1719       /* that the function is not on this menu. */
1720       return FALSE;
1721     end if;
1722 
1723     l_sub_menu_id := menulist(menulist_cur);
1724 
1725     -- See whether the current menu is excluded or not.
1726     entry_excluded := FALSE;
1727     begin
1728       if(    (l_sub_menu_id is not NULL)
1729          and (exclusions(l_sub_menu_id) = 'M')) then
1730         entry_excluded := TRUE;
1731       end if;
1732     exception
1733       when no_data_found then
1734         null;
1735     end;
1736 
1737     if (entry_excluded) then
1738       last_index := 0; /* Indicate that no rows were returned */
1739     else
1740       /* This menu isn't excluded, so find out whats entries are on it. */
1741       if (G_BULK_COLLECTS_SUPPORTED='TRUE') then
1742         open get_mnes_c for l_mnes_dynamic_sql USING
1743             l_sub_menu_id;
1744 
1745         fetch get_mnes_c bulk collect into tbl_menu_id, tbl_ent_seq,
1746              tbl_func_id, tbl_submnu_id, tbl_gnt_flg;
1747         close get_mnes_c;
1748 
1749         -- See if we found any rows. If not set last_index to zero.
1750         begin
1751           if((tbl_menu_id.FIRST is NULL) or (tbl_menu_id.FIRST <> 1)) then
1752             last_index := 0;
1753           else
1754             if (tbl_menu_id.FIRST is not NULL) then
1755               last_index := tbl_menu_id.LAST;
1756             else
1757               last_index := 0;
1758             end if;
1759           end if;
1760         exception
1761           when others then
1762             last_index := 0;
1763         end;
1764       else
1765         z:= 0;
1766         OPEN get_mnes_c FOR l_mnes_dynamic_sql USING
1767             l_sub_menu_id;
1768         LOOP
1769             FETCH get_mnes_c INTO l_mnes_menu_id,
1770                                   l_mnes_entry_sequence,
1771                                   l_mnes_function_id,
1772                                   l_mnes_sub_menu_id,
1773                                   l_mnes_grant_flag;
1774             EXIT WHEN get_mnes_c%NOTFOUND;
1775             tbl_menu_id(z) := l_mnes_menu_id;
1776             tbl_ent_seq(z) := l_mnes_entry_sequence;
1777             tbl_func_id(z) := l_mnes_function_id;
1778             tbl_submnu_id (z):= l_mnes_sub_menu_id;
1779             tbl_gnt_flg(z) := l_mnes_grant_flag;
1780         END LOOP;
1781         CLOSE get_mnes_c;
1782 
1783         last_index := z;
1784       end if;
1785 
1786     end if; /* entry_excluded */
1787 
1788     -- Process each of the child entries fetched
1789     for i in 1 .. last_index loop
1790       -- Check if there is an exclusion rule for this entry
1791       entry_excluded := FALSE;
1792       begin
1793         if(    (tbl_func_id(i) is not NULL)
1794            and (exclusions(tbl_func_id(i)) = 'F')) then
1795           entry_excluded := TRUE;
1796         end if;
1797       exception
1798         when no_data_found then
1799           null;
1800       end;
1801 
1802       -- Skip this entry if it's excluded
1803       if (not entry_excluded) then
1804         -- Check if this is a matching function.  If so, return success.
1805         if(    (tbl_func_id(i) = p_function_id)
1806            and (tbl_gnt_flg(i) = 'Y'))
1807         then
1808           G_ROLE_NAME_LIST(G_PV_COUNT)           := p_role_name;
1809           G_MENU_ID_LIST(G_PV_COUNT)             := tbl_menu_id(i);
1810           G_FUNCTION_ID_LIST(G_PV_COUNT)         := p_function_id;
1811           G_RESPONSIBILITY_ID_LIST(G_PV_COUNT)   := p_resp_id;
1812           G_ENTRY_OBJECT_TYPE_LIST(G_PV_COUNT)   := p_entry_object_type_list;
1813           G_GROUP_CODE_LIST(G_PV_COUNT)          := p_group_code; -- 05.24.2005 tsho: AMW.E Incompatible Sets
1814           G_PV_COUNT := G_PV_COUNT +1;
1815           return TRUE;
1816         end if;
1817 
1818         -- If this is a submenu, then add it to the end of the
1819         -- working list for processing.
1820         if (tbl_submnu_id(i) is not NULL) then
1821           menulist(menulist_size) := tbl_submnu_id(i);
1822           menulist_size := menulist_size + 1;
1823         end if;
1824       end if; -- End if not excluded
1825     end loop;  -- For loop processing child entries
1826 
1827     -- Advance to next menu on working list
1828     menulist_cur := menulist_cur + 1;
1829   end loop;
1830 
1831   -- We couldn't find the function anywhere, so it's not available
1832   return FALSE;
1833 
1834 END PROCESS_MENU_TREE_DOWN_FOR_MN;
1835 
1836 
1837 
1838 
1839 -- ===============================================================
1840 -- Private Procedure name
1841 --          BUILD_ROLE_AND_RESP_HIER
1842 --
1843 -- Purpose
1844 --          Plow through the role/resp hierarchy
1845 -- History
1846 --          05.23.2006 dliao created
1847 -- ===============================================================
1848 PROCEDURE BUILD_ROLE_AND_RESP_HIER(
1849 P_ROLE_NAME_LIST_HIER          in   G_VARCHAR2_LONG_TABLE,
1850 P_RESPONSIBILITY_ID_LIST_HIER   in G_NUMBER_TABLE,
1851 P_MENU_ID_LIST_HIER           in G_NUMBER_TABLE,
1852 P_FUNCTION_ID_LIST_HIER       in  G_NUMBER_TABLE,
1853 P_ENTRY_OBJECT_TYPE_LIST_HIER  in G_VARCHAR2_CODE_TABLE,
1854 P_GROUP_CODE_LIST_HIER          in G_VARCHAR2_CODE_TABLE
1855 )
1856 IS
1857 
1858   L_API_NAME                  CONSTANT VARCHAR2(30) := 'BUILD_ROLE_AND_RESP_HIER';
1859   L_API_VERSION_NUMBER        CONSTANT NUMBER		  := 1.0;
1860 
1861 p_superiors WF_ROLE_HIERARCHY.RELTAB;
1862 p_subordinates WF_ROLE_HIERARCHY.RELTAB;
1863 
1864 BEGIN
1865 
1866 G_ROLE_NAME_LIST_HIER := P_ROLE_NAME_LIST_HIER;
1867 G_RESPONSIBILITY_ID_LIST_HIER := P_RESPONSIBILITY_ID_LIST_HIER;
1868 G_MENU_ID_LIST_HIER    := P_MENU_ID_LIST_HIER;
1869 G_FUNCTION_ID_LIST_HIER    := P_FUNCTION_ID_LIST_HIER;
1870 G_ENTRY_OBJECT_TYPE_LIST_HIER   := P_ENTRY_OBJECT_TYPE_LIST_HIER;
1871 G_GROUP_CODE_LIST_HIER       := P_GROUP_CODE_LIST_HIER;
1872 
1873 G_PV_COUNT_HIER := P_FUNCTION_ID_LIST_HIER.COUNT;
1874 
1875 
1876 	FOR i IN 1 .. P_FUNCTION_ID_LIST_HIER.COUNT LOOP
1877 	wf_role_hierarchy.getrelationships(P_ROLE_NAME_LIST_HIER(i),p_superiors,p_subordinates,'SUBORDINATES');
1878 
1879   	IF p_subordinates.count > 0 THEN
1880     		FOR k IN p_subordinates.first..p_subordinates.last LOOP
1881       		IF p_subordinates.exists(k) THEN
1882 
1883       		     G_PV_COUNT_HIER := G_PV_COUNT_HIER + 1;
1884 
1885       		G_ROLE_NAME_LIST_HIER(G_PV_COUNT_HIER) := p_subordinates(k).sub_name  ;
1886 		G_RESPONSIBILITY_ID_LIST_HIER(G_PV_COUNT_HIER) :=   P_RESPONSIBILITY_ID_LIST_HIER(i);
1887 		G_MENU_ID_LIST_HIER(G_PV_COUNT_HIER) :=  P_MENU_ID_LIST_HIER(i);
1888 		G_FUNCTION_ID_LIST_HIER(G_PV_COUNT_HIER) :=  P_FUNCTION_ID_LIST_HIER(i);
1889 		G_ENTRY_OBJECT_TYPE_LIST_HIER(G_PV_COUNT_HIER) :=  P_ENTRY_OBJECT_TYPE_LIST_HIER(i);
1890 		G_GROUP_CODE_LIST_HIER(G_PV_COUNT_HIER) :=   P_GROUP_CODE_LIST_HIER(i);
1891 
1892       		END IF;
1893     		END LOOP;-- end of p_subordinates
1894 
1895  	 END IF;
1896 
1897 
1898 	END LOOP; -- end of P_FUNCTION_ID_LIST_HIER
1899 
1900 EXCEPTION
1901     WHEN others then
1902         RAISE;
1903 END BUILD_ROLE_AND_RESP_HIER;
1904 
1905 
1906 
1907 -- ===============================================================
1908 -- Procedure name
1909 --          Update_Role_Constraint_Denorm
1910 --
1911 -- Purpose
1912 --          populate AMW_ROLE_CONSTRAINT_DENORM table
1913 -- Params
1914 --          p_constraint_rev_id       := input constraint_rev_id (Default is NULL)
1915 --                                       if p_constraint_rev_id is specified, only update/create
1916 --                                       the corresponding role/resp with that constraint.
1917 --
1918 -- History
1919 -- 		  	07/14/2005    tsho     Create
1920 --          08/03/2005    tsho     Consider Responsibility Waivers, leave User Waiver check to the run-time
1921 --          09/16/2005    tsho     Consider Concurrent Program and Exclusion (function/menu exclusion from Responsibility)
1922 -- ===============================================================
1923 Procedure Update_Role_Constraint_Denorm (
1924     errbuf                       OUT  NOCOPY VARCHAR2,
1925     retcode                      OUT  NOCOPY VARCHAR2,
1926     p_constraint_rev_id     IN  NUMBER := NULL
1927 )
1928 IS
1929 L_API_NAME                  CONSTANT VARCHAR2(30) := 'Update_Role_Constraint_Denorm';
1930 L_API_VERSION_NUMBER        CONSTANT NUMBER		  := 1.0;
1931 
1932 TYPE respCurTyp IS REF CURSOR;
1933 role_c respCurTyp;
1934 resp_c respCurTyp;
1935 
1936 p_superiors WF_ROLE_HIERARCHY.RELTAB;
1937 p_subordinates WF_ROLE_HIERARCHY.RELTAB;
1938 
1939 l_g_role_name             VARCHAR2(320);
1940 l_g_responsibility_id     NUMBER;
1941 l_g_menu_id               NUMBER;
1942 l_g_function_id           NUMBER;
1943 l_g_entry_object_type    VARCHAR2(30);
1944 l_g_group_code           VARCHAR2(30);
1945 
1946 
1947 -- 09.16.2005 tsho: Consider Concurrent Program and Exclusion (function/menu exclusion from Responsibility)
1948 -- seperate the responsibility query from role
1949 -- 05.23.2006 dliao: remove the grant_flag
1950 l_role_dynamic_sql   VARCHAR2(4000)  :=
1951         '(SELECT gra.GRANTEE_KEY ROLE_NAME, gra.GRANTEE_ORIG_SYSTEM_ID as responsibility_id, gra.menu_id, ce.function_id, ce.object_type, ce.group_code '
1952       ||'  FROM AMW_CONSTRAINT_ENTRIES ce '
1953       ||'      ,'||G_AMW_GRANTS ||' gra '
1954       ||'      ,'||G_AMW_COMPILED_MENU_FUNCTIONS ||' cmf '
1955       ||' WHERE gra.menu_id = cmf.menu_id '
1956       ||'   AND cmf.function_id = ce.function_id '
1957       --and cmf.grant_flag = ''Y'' '
1958       ||'   AND ce.CONSTRAINT_REV_ID = :1 '
1959       ||'   AND gra.INSTANCE_TYPE = ''GLOBAL'' '
1960       ||'   AND gra.OBJECT_ID = -1 '
1961       ||'   AND gra.GRANTEE_TYPE = ''GROUP'' '
1962       ||'   AND gra.start_date <= sysdate AND (gra.end_date >= sysdate or gra.end_date is null) '
1963       ||' UNION '
1964       ||' SELECT gra.GRANTEE_KEY ROLE_NAME, gra.GRANTEE_ORIG_SYSTEM_ID as responsibility_id, gra.menu_id, ce.function_id, ce.object_type, ce.group_code '
1965       ||'  FROM AMW_CONSTRAINT_ENTRIES ce '
1966       ||'      ,'||G_AMW_GRANTS ||' gra '
1967       ||'      ,'||G_AMW_COMPILED_MENU_FUNCTIONS ||' cmf '
1968       ||' WHERE gra.menu_id = cmf.menu_id '
1969       ||'   AND cmf.function_id = ce.function_id '
1970       --and cmf.grant_flag = ''Y'' '
1971       ||'   AND ce.CONSTRAINT_REV_ID = :2 '
1972       ||'   AND gra.INSTANCE_TYPE = ''GLOBAL'' '
1973       ||'   AND gra.OBJECT_ID = -1 '
1974       ||'   AND gra.GRANTEE_TYPE = ''GLOBAL'' '
1975       ||'   AND gra.start_date <= sysdate AND (gra.end_date >= sysdate or gra.end_date is null) '
1976       ||') UNION ALL '
1977       ||' SELECT to_char(null) role_name, resp.responsibility_id, resp.request_group_id menu_id, ce.function_id, ce.object_type, ce.group_code '
1978       ||' FROM  '||G_AMW_RESPONSIBILITY ||' resp '
1979       ||'      ,'||G_AMW_REQUEST_GROUP_UNITS ||' rgu '
1980       ||'      ,AMW_CONSTRAINT_ENTRIES ce '
1981       ||' WHERE resp.request_group_id = rgu.request_group_id '
1982       ||'   AND rgu.request_unit_type = ''P'' '
1983       ||'   AND rgu.request_unit_id = ce.function_id AND ce.object_type = ''CP'' '
1984       ||'   AND ce.CONSTRAINT_REV_ID = :3 '
1985       ||'   AND resp.responsibility_id NOT IN (select cw.pk1 from amw_constraint_waivers_vl cw '
1986       ||'                 where cw.constraint_rev_id=ce.CONSTRAINT_REV_ID '
1987       ||'                 and cw.object_type=''RESP'' '
1988       ||'                 and cw.start_date<=sysdate '
1989       ||'                 and (cw.end_date >= sysdate or cw.end_date is null)) '
1990       ||'   AND resp.start_date <= sysdate AND (resp.end_date >= sysdate or resp.end_date is null) '
1991       ;
1992 
1993 -- 09.16.2005 tsho: Consider Exclusion (function/menu exclusion from Responsibility)
1994 -- seperate the responsibility query from role
1995 l_applcation_id_list        G_NUMBER_TABLE;
1996 l_responsibility_id_list    G_NUMBER_TABLE;
1997 l_menu_id_list              G_NUMBER_TABLE;
1998 l_function_id_list          G_NUMBER_TABLE;
1999 l_role_name_id_list         G_VARCHAR2_LONG_TABLE;
2000 l_entry_object_type_list    G_VARCHAR2_CODE_TABLE;
2001 l_group_code_list           G_VARCHAR2_CODE_TABLE;
2002 --17.12.06 psomanat : The FND creates a role for each responsibity.So the role name is added here.
2003 l_resp_dynamic_sql   VARCHAR2(2000)  :=
2004         ' SELECT war.name, resp.application_id, resp.responsibility_id, resp.menu_id, ce.function_id, ce.object_type, ce.group_code '
2005       ||'  FROM AMW_CONSTRAINT_ENTRIES ce '
2006       ||'      ,'||G_AMW_RESPONSIBILITY_VL ||' resp '
2007       ||'      ,'||G_AMW_COMPILED_MENU_FUNCTIONS ||' cmf '
2008       ||'      ,'||G_AMW_ALL_ROLES_VL ||' war '
2009       ||' WHERE resp.menu_id = cmf.menu_id '
2010       ||'   AND cmf.function_id = ce.function_id and cmf.grant_flag = ''Y'' '
2011       ||'   AND (ce.OBJECT_TYPE is null OR ce.OBJECT_TYPE = ''FUNC'') '
2012       ||'   AND ce.CONSTRAINT_REV_ID = :1 '
2013       ||'   AND resp.responsibility_id NOT IN (select cw.pk1 from amw_constraint_waivers_vl cw '
2014       ||'                 where cw.constraint_rev_id=ce.CONSTRAINT_REV_ID '
2015       ||'                 and cw.object_type=''RESP'' '
2016       ||'                 and cw.start_date<=sysdate '
2017       ||'                 and (cw.end_date >= sysdate or cw.end_date is null)) '
2018       ||'   AND resp.start_date <= sysdate AND (resp.end_date >= sysdate or resp.end_date is null) '
2019       ||'   AND resp.responsibility_name = war.display_name '
2020       ||'   AND war.ORIG_SYSTEM = ''FND_RESP'' '
2021       ||'   AND STATUS = ''ACTIVE'' ';
2022 
2023 -- find all valid constraints
2024 CURSOR c_all_valid_constraints IS
2025       SELECT constraint_rev_id
2026         FROM amw_constraints_b
2027        WHERE start_date <= sysdate AND (end_date IS NULL OR end_date >= sysdate);
2028 l_all_valid_constraints c_all_valid_constraints%ROWTYPE;
2029 
2030 --09.20.2005 tsho Consider Exclusion
2031 -- store the access right
2032 l_accessible    BOOLEAN;
2033 TYPE exclFuncCurTyp IS REF CURSOR;
2034 excl_func_c exclFuncCurTyp;
2035 l_excl_func_count     NUMBER;
2036 
2037 l_excl_func_dynamic_sql   VARCHAR2(200)  :=
2038       'SELECT count(*) '
2039     ||'  FROM '||G_AMW_RESP_FUNCTIONS
2040     ||'  WHERE application_id = :1 '
2041     ||'  AND responsibility_id = :2 '
2042     ||'  AND rule_type = :3 '
2043     ||'  AND action_id = :4 ';
2044 
2045 BEGIN
2046     IF p_constraint_rev_id IS NULL THEN
2047         -- delete all the records from amw_role_constraint_denorm
2048         DELETE FROM AMW_ROLE_CONSTRAINT_DENORM;
2049 
2050         -- check all constraints
2051         OPEN c_all_valid_constraints;
2052         LOOP
2053             FETCH c_all_valid_constraints INTO l_all_valid_constraints;
2054             EXIT WHEN c_all_valid_constraints%NOTFOUND;
2055 
2056             -- clear global list for each constraint
2057             Clear_List();
2058 
2059             OPEN role_c FOR l_role_dynamic_sql USING
2060                 l_all_valid_constraints.constraint_rev_id, l_all_valid_constraints.constraint_rev_id, l_all_valid_constraints.constraint_rev_id;
2061             FETCH role_c BULK COLLECT INTO
2062                 G_ROLE_NAME_LIST
2063                ,G_RESPONSIBILITY_ID_LIST
2064                ,G_MENU_ID_LIST
2065                ,G_FUNCTION_ID_LIST
2066                ,G_ENTRY_OBJECT_TYPE_LIST
2067                ,G_GROUP_CODE_LIST;
2068             CLOSE role_c;
2069 
2070 
2071          BUILD_ROLE_AND_RESP_HIER(
2072                         P_ROLE_NAME_LIST_HIER => G_ROLE_NAME_LIST,
2073                         P_RESPONSIBILITY_ID_LIST_HIER   => G_RESPONSIBILITY_ID_LIST,
2074                         P_MENU_ID_LIST_HIER   => G_MENU_ID_LIST,
2075                         P_FUNCTION_ID_LIST_HIER   => G_FUNCTION_ID_LIST,
2076                         P_ENTRY_OBJECT_TYPE_LIST_HIER  => G_ENTRY_OBJECT_TYPE_LIST,
2077                         P_GROUP_CODE_LIST_HIER    => G_GROUP_CODE_LIST);
2078 
2079 	IF(G_FUNCTION_ID_LIST_HIER.COUNT > 0) THEN
2080             FORALL i IN 1 .. G_FUNCTION_ID_LIST_HIER.COUNT
2081                 INSERT INTO AMW_ROLE_CONSTRAINT_DENORM
2082                 VALUES(sysdate     -- last_update_date
2083                       ,G_USER_ID   -- last_updated_by
2084                       ,G_LOGIN_ID  -- last_update_login
2085                       ,sysdate     -- creation_date
2086                       ,G_USER_ID   -- created_by
2087                       ,G_FUNCTION_ID_LIST_HIER(i)    -- function_id
2088                       ,G_MENU_ID_LIST_HIER(i)        -- menu_id
2089                       ,l_all_valid_constraints.constraint_rev_id    -- constraint_rev_id
2090                       ,G_ENTRY_OBJECT_TYPE_LIST_HIER(i)                  -- object_type
2091                       ,G_GROUP_CODE_LIST_HIER(i)     -- group_code
2092                       ,G_ROLE_NAME_LIST_HIER(i)      -- role_name
2093                       ,G_RESPONSIBILITY_ID_LIST_HIER(i));                -- responsibility_id
2094 	END IF;
2095 
2096             -- 09.20.2005 tsho: consider Exclusion
2097             -- clear global list for each constraint
2098             Clear_List();
2099             l_applcation_id_list.delete();
2100             l_responsibility_id_list.delete();
2101             l_role_name_id_list.delete();
2102             l_menu_id_list.delete();
2103             l_function_id_list.delete();
2104             l_entry_object_type_list.delete();
2105             l_group_code_list.delete();
2106 
2107             OPEN resp_c FOR l_resp_dynamic_sql USING
2108                 l_all_valid_constraints.constraint_rev_id;
2109             FETCH resp_c BULK COLLECT INTO
2110                 l_role_name_id_list
2111                ,l_applcation_id_list
2112                ,l_responsibility_id_list
2113                ,l_menu_id_list
2114                ,l_function_id_list
2115                ,l_entry_object_type_list
2116                ,l_group_code_list;
2117             CLOSE resp_c;
2118 
2119             FOR j IN 1 .. l_function_id_list.COUNT
2120             LOOP
2121                 -- check function exclusion
2122                 OPEN excl_func_c FOR l_excl_func_dynamic_sql USING
2123                     l_applcation_id_list(j), l_responsibility_id_list(j), 'F', l_function_id_list(j);
2124                 FETCH excl_func_c INTO l_excl_func_count;
2125                 CLOSE excl_func_c;
2126 
2127                 IF (l_excl_func_count > 0) THEN
2128                     -- the function i is excluded from the reponsibility j, check next responsibility
2129                     l_accessible := FALSE;
2130                 ELSE
2131                     -- need to check if any menu excluded from the responsibility j
2132                     l_accessible := PROCESS_MENU_TREE_DOWN_FOR_MN(
2133                                        p_menu_id        => l_menu_id_list(j),
2134                                        p_function_id    => l_function_id_list(j),
2135                                        p_appl_id        => l_applcation_id_list(j),
2136                                        p_resp_id        => l_responsibility_id_list(j),
2137                                        p_role_name      => l_role_name_id_list(j),
2138                                        p_entry_object_type_list => l_entry_object_type_list(j),
2139                                        p_group_code     => l_group_code_list(j));
2140 
2141                         BUILD_ROLE_AND_RESP_HIER(
2142                         P_ROLE_NAME_LIST_HIER => G_ROLE_NAME_LIST,
2143                         P_RESPONSIBILITY_ID_LIST_HIER   => G_RESPONSIBILITY_ID_LIST,
2144                         P_MENU_ID_LIST_HIER   => G_MENU_ID_LIST,
2145                         P_FUNCTION_ID_LIST_HIER   => G_FUNCTION_ID_LIST,
2146                         P_ENTRY_OBJECT_TYPE_LIST_HIER  => G_ENTRY_OBJECT_TYPE_LIST,
2147                         P_GROUP_CODE_LIST_HIER    => G_GROUP_CODE_LIST);
2148 
2149 
2150                 END IF; -- end of if: l_excl_func_id IS NOT NULL
2151 
2152             END LOOP; --end of for: l_function_id_list
2153 
2154               -- populate non-exclusion function to defnorm table
2155                IF(G_FUNCTION_ID_LIST_HIER.COUNT > 0) THEN
2156             FORALL i IN 1 .. G_FUNCTION_ID_LIST_HIER.COUNT
2157 
2158                 INSERT INTO AMW_ROLE_CONSTRAINT_DENORM
2159                 VALUES(sysdate     -- last_update_date
2160                       ,G_USER_ID   -- last_updated_by
2161                       ,G_LOGIN_ID  -- last_update_login
2162                       ,sysdate     -- creation_date
2163                       ,G_USER_ID   -- created_by
2164                       ,G_FUNCTION_ID_LIST_HIER(i)    -- function_id
2165                       ,G_MENU_ID_LIST_HIER(i)        -- menu_id
2166                       ,l_all_valid_constraints.constraint_rev_id    -- constraint_rev_id
2167                       ,G_ENTRY_OBJECT_TYPE_LIST_HIER(i)                  -- object_type
2168                       ,G_GROUP_CODE_LIST_HIER(i)     -- group_code
2169                       ,G_ROLE_NAME_LIST_HIER(i)      -- role_name
2170                       ,G_RESPONSIBILITY_ID_LIST_HIER(i));                -- responsibility_id
2171 
2172 	   END IF;  --end of g_function_id_list_hier.count > 0
2173 
2174         END LOOP;
2175 
2176         CLOSE c_all_valid_constraints;
2177     ELSE
2178         -- check specified constraint
2179         -- delete the records from amw_role_constraint_denorm for the specified constraint
2180         DELETE FROM AMW_ROLE_CONSTRAINT_DENORM
2181         WHERE constraint_rev_id = p_constraint_rev_id;
2182 
2183         -- clear global list for each constraint
2184         Clear_List();
2185 
2186 
2187         OPEN role_c FOR l_role_dynamic_sql USING
2188             p_constraint_rev_id, p_constraint_rev_id, p_constraint_rev_id;
2189         FETCH role_c BULK COLLECT INTO
2190             G_ROLE_NAME_LIST
2191            ,G_RESPONSIBILITY_ID_LIST
2192            ,G_MENU_ID_LIST
2193            ,G_FUNCTION_ID_LIST
2194            ,G_ENTRY_OBJECT_TYPE_LIST
2195            ,G_GROUP_CODE_LIST;
2196         CLOSE role_c;
2197 
2198          BUILD_ROLE_AND_RESP_HIER(
2199                         P_ROLE_NAME_LIST_HIER => G_ROLE_NAME_LIST,
2200                         P_RESPONSIBILITY_ID_LIST_HIER   => G_RESPONSIBILITY_ID_LIST,
2201                         P_MENU_ID_LIST_HIER   => G_MENU_ID_LIST,
2202                         P_FUNCTION_ID_LIST_HIER   => G_FUNCTION_ID_LIST,
2203                         P_ENTRY_OBJECT_TYPE_LIST_HIER  => G_ENTRY_OBJECT_TYPE_LIST,
2204                         P_GROUP_CODE_LIST_HIER    => G_GROUP_CODE_LIST);
2205 
2206 	IF(G_FUNCTION_ID_LIST_HIER.COUNT > 0) THEN
2207         FORALL i IN 1 .. G_FUNCTION_ID_LIST_HIER.COUNT
2208             INSERT INTO AMW_ROLE_CONSTRAINT_DENORM
2209             VALUES(sysdate     -- last_update_date
2210                   ,G_USER_ID   -- last_updated_by
2211                   ,G_LOGIN_ID  -- last_update_login
2212                   ,sysdate     -- creation_date
2213                   ,G_USER_ID   -- created_by
2214                   ,G_FUNCTION_ID_LIST_HIER(i)    -- function_id
2215                   ,G_MENU_ID_LIST_HIER(i)        -- menu_id
2216                   ,p_constraint_rev_id      -- constraint_rev_id
2217                   ,G_ENTRY_OBJECT_TYPE_LIST_HIER(i)                  -- object_type
2218                   ,G_GROUP_CODE_LIST_HIER(i)     -- group_code
2219                   ,G_ROLE_NAME_LIST_HIER(i)      -- role_name
2220                   ,G_RESPONSIBILITY_ID_LIST_HIER(i));                -- responsibility_id
2221 	END IF;
2222         -- 09.20.2005 tsho: consider Exclusion
2223         -- clear global list for each constraint
2224         Clear_List();
2225         l_applcation_id_list.delete();
2226         l_responsibility_id_list.delete();
2227         l_role_name_id_list.delete();
2228         l_menu_id_list.delete();
2229         l_function_id_list.delete();
2230         l_entry_object_type_list.delete();
2231         l_group_code_list.delete();
2232 
2233 
2234 
2235         OPEN resp_c FOR l_resp_dynamic_sql USING
2236             p_constraint_rev_id;
2237         FETCH resp_c BULK COLLECT INTO
2238             l_role_name_id_list
2239            ,l_applcation_id_list
2240            ,l_responsibility_id_list
2241            ,l_menu_id_list
2242            ,l_function_id_list
2243            ,l_entry_object_type_list
2244            ,l_group_code_list;
2245         CLOSE resp_c;
2246 
2247         FOR j IN 1 .. l_function_id_list.COUNT
2248         LOOP
2249             -- check function exclusion
2250             OPEN excl_func_c FOR l_excl_func_dynamic_sql USING
2251                 l_applcation_id_list(j), l_responsibility_id_list(j), 'F', l_function_id_list(j);
2252             FETCH excl_func_c INTO l_excl_func_count;
2253             CLOSE excl_func_c;
2254             IF (l_excl_func_count > 0) THEN
2255                 -- the function i is excluded from the reponsibility j, check next responsibility
2256                 l_accessible := FALSE;
2257             ELSE
2258                 -- need to check if any menu excluded from the responsibility j
2259                 l_accessible := PROCESS_MENU_TREE_DOWN_FOR_MN(
2260                                    p_menu_id        => l_menu_id_list(j),
2261                                    p_function_id    => l_function_id_list(j),
2262                                    p_appl_id        => l_applcation_id_list(j),
2263                                    p_resp_id        => l_responsibility_id_list(j),
2264                                    p_role_name      => l_role_name_id_list(j),
2265                                    p_entry_object_type_list => l_entry_object_type_list(j),
2266                                    p_group_code     => l_group_code_list(j));
2267 
2268                      BUILD_ROLE_AND_RESP_HIER(
2269                         P_ROLE_NAME_LIST_HIER => G_ROLE_NAME_LIST,
2270                         P_RESPONSIBILITY_ID_LIST_HIER   => G_RESPONSIBILITY_ID_LIST,
2271                         P_MENU_ID_LIST_HIER   => G_MENU_ID_LIST,
2272                         P_FUNCTION_ID_LIST_HIER   => G_FUNCTION_ID_LIST,
2273                         P_ENTRY_OBJECT_TYPE_LIST_HIER  => G_ENTRY_OBJECT_TYPE_LIST,
2274                         P_GROUP_CODE_LIST_HIER    => G_GROUP_CODE_LIST);
2275 
2276 
2277             END IF; -- end of if: l_excl_func_id IS NOT NULL
2278         END LOOP; --end of for: l_function_id_list
2279 
2280 
2281         -- populate non-exclusion function to defnorm table
2282            IF(G_FUNCTION_ID_LIST_HIER.COUNT > 0) THEN
2283             FORALL i IN 1 .. G_FUNCTION_ID_LIST_HIER.COUNT
2284 
2285                 INSERT INTO AMW_ROLE_CONSTRAINT_DENORM
2286                 VALUES(sysdate     -- last_update_date
2287                       ,G_USER_ID   -- last_updated_by
2288                       ,G_LOGIN_ID  -- last_update_login
2289                       ,sysdate     -- creation_date
2290                       ,G_USER_ID   -- created_by
2291                       ,G_FUNCTION_ID_LIST_HIER(i)    -- function_id
2292                       ,G_MENU_ID_LIST_HIER(i)        -- menu_id
2293                       ,p_constraint_rev_id    -- constraint_rev_id
2294                       ,G_ENTRY_OBJECT_TYPE_LIST_HIER(i)                  -- object_type
2295                       ,G_GROUP_CODE_LIST_HIER(i)     -- group_code
2296                       ,G_ROLE_NAME_LIST_HIER(i)      -- role_name
2297                       ,G_RESPONSIBILITY_ID_LIST_HIER(i));                -- responsibility_id
2298 	    END IF; --end of if g_function_id_list_hier.count > 0
2299 
2300     END IF; --end of if: p_constraint_rev_id = NULL
2301 
2302     COMMIT;
2303 
2304 EXCEPTION
2305     WHEN others then
2306         RAISE;
2307 
2308 END Update_Role_Constraint_Denorm;
2309 
2310 -- ===============================================================
2311 -- Function name
2312 --          Get_Violat_New_Role_List
2313 --
2314 -- Purpose
2315 --          get a flat string list of new role display name, which together with this user's
2316 --          exisiting role/resp , or together with those new assigned role(among p_role_names_string)
2317 --          may violate the specified constraint
2318 --
2319 -- Params
2320 --          p_user_id            := input fnd user_id
2321 --          p_constraint_rev_id  := input constraint_rev_id
2322 --          p_constraint_type_code  := input constraint type for p_constraint_rev_id
2323 --          p_new_role_names_string  := input a string list of new roles assigning to this user,
2324 --                                  the role_name is seperated by ','
2325 --
2326 -- Return
2327 --          a string list of role display names which violates the specified constraint,
2328 --          each display name is seperated by ','
2329 --
2330 -- History
2331 -- 		  	07/27/2005    tsho     Create
2332 -- ===============================================================
2333 Function Get_Violat_New_Role_List (
2334     p_user_id                   IN  NUMBER,
2335     p_constraint_rev_id         IN  NUMBER,
2336     p_constraint_type_code      IN  VARCHAR2,
2337     p_new_role_names_string     IN  VARCHAR2
2338 ) RETURN VARCHAR2
2339 IS
2340 L_API_NAME                  CONSTANT VARCHAR2(30) := 'Get_Violat_New_Role_List';
2341 L_API_VERSION_NUMBER        CONSTANT NUMBER		  := 1.0;
2342 
2343 -- store the new role this user has against this constraint
2344 l_new_role_table JTF_VARCHAR2_TABLE_400;
2345 
2346 -- store the return value
2347 l_new_role_string VARCHAR2(32767);
2348 
2349 l_new_role_names_string VARCHAR2(32767):=p_new_role_names_string;
2350 
2351 TYPE refCurTyp IS REF CURSOR;
2352 new_role_c refCurTyp;
2353 
2354 -- find new roles this user has (results in violating the specified constraint)
2355 l_new_role_dynamic_sql   VARCHAR2(500)  :=
2356     'select distinct rv.display_name '
2357   ||'  from amw_role_constraint_denorm rcd '
2358   ||'      ,'||G_AMW_ALL_ROLES_VL||' rv '
2359   ||'  where rcd.constraint_rev_id = :1 '
2360   ||'    and (rcd.role_name = rv.name or (rv.orig_system = ''FND_RESP'' and rcd.responsibility_id = rv.orig_system_id ) ) '
2361   ||'    and rv.name in (:2) ';
2362 
2363 
2364  -- ptulasi : 08/22/2007
2365  -- Bug 5558490 : Added below query to find new responsibilities user has
2366  -- (results in violating the specified constraint)
2367  l_new_resp_dynamic_sql   VARCHAR2(1500)  :=
2368   ' SELECT distinct rv.display_name '
2369   ||' FROM fnd_responsibility_vl frv '
2370   ||'      ,'||G_AMW_ALL_ROLES_VL||' rv ,'
2371   ||'      amw_constraint_entries ace'
2372   ||' WHERE rv.name IN (:1)'
2373   ||'       AND frv.responsibility_id = ace.function_id '
2374   ||'       AND frv.APPLICATION_ID = ace.APPLICATION_ID '
2375   ||'       AND ace.object_type = ''RESP'''
2376   ||'       AND ace.constraint_rev_id = :2'
2377   ||'       AND ( rv.display_name = frv.responsibility_name OR ( rv.orig_system = ''FND_RESP'' AND frv.responsibility_id = rv.orig_system_id ))'
2378   ||'       AND (frv.end_date is null OR (frv.end_date is not null AND frv.end_date > sysdate))';
2379 
2380 BEGIN
2381   l_new_role_string := NULL;
2382 
2383   IF (p_user_id IS NOT NULL AND p_constraint_rev_id IS NOT NULL AND p_constraint_type_code IS NOT NULL AND p_new_role_names_string IS NOT NULL) THEN
2384 
2385     -- 24-12-2005 : psomanat
2386     -- When the Send_Notif_To_Process_Owner call this function the role name
2387     -- does not have the @ delimiter at the last.
2388     IF (instr(l_new_role_names_string,'@') = 0) THEN
2389        l_new_role_names_string := l_new_role_names_string || '@';
2390     END IF;
2391 
2392     WHILE (substr(l_new_role_names_string,1,instr(l_new_role_names_string,'@')-1) IS NOT NULL)
2393     LOOP
2394 
2395         -- ptulasi : 08/22/2007
2396         -- Bug 5558490 : Added below code to execute the query based on the constraint type
2397         IF p_constraint_type_code <> 'RESP' THEN
2398            OPEN new_role_c FOR l_new_role_dynamic_sql USING
2399               p_constraint_rev_id, substr(l_new_role_names_string,1,instr(l_new_role_names_string,'@')-1) ;
2400         ELSE
2401            OPEN new_role_c FOR l_new_resp_dynamic_sql USING
2402               substr(l_new_role_names_string,1,instr(l_new_role_names_string,'@')-1), p_constraint_rev_id;
2403         END IF;
2404 
2405         FETCH new_role_c BULK COLLECT INTO l_new_role_table;
2406         CLOSE new_role_c;
2407 
2408         IF l_new_role_table IS NOT NULL AND l_new_role_table.FIRST IS NOT NULL THEN
2409             IF l_new_role_string IS NULL THEN
2410                 l_new_role_string :=l_new_role_table(1);
2411             ELSE
2412                 l_new_role_string :=l_new_role_string||', '||l_new_role_table(1);
2413             END IF;
2414             FOR i in 2 .. l_new_role_table.COUNT
2415             LOOP
2416                 l_new_role_string := l_new_role_string||', '||l_new_role_table(i);
2417             END LOOP;
2418         END IF; -- end of if: l_new_role_table IS NOT NULL
2419         l_new_role_names_string:=substr(l_new_role_names_string,instr(l_new_role_names_string,'@')+1);
2420     END LOOP;
2421   END IF; --end of if: p_user_id IS NOT NULL AND p_constraint_rev_id IS NOT NULL AND p_constraint_type_code IS NOT NULL AND p_new_role_names_string IS NOT NULL
2422 return l_new_role_string;
2423 END Get_Violat_New_Role_List;
2424 
2425 
2426 -- ===============================================================
2427 -- Function name
2428 --          Get_Violat_Existing_Role_List
2429 --
2430 -- Purpose
2431 --          get a flat string list of this user's existing role display name, together with those new assigned role(among p_role_names_string)
2432 --          may violate the specified constraint
2433 --
2434 -- Params
2435 --          p_user_id            := input fnd user_id
2436 --          p_constraint_rev_id  := input constraint_rev_id
2437 --          p_constraint_type_code  := input constraint type for p_constraint_rev_id
2438 --
2439 -- Return
2440 --          a string list of role display names which violates the specified constraint,
2441 --          each display name is seperated by ','
2442 --
2443 -- History
2444 -- 		  	07/27/2005    tsho     Create
2445 -- ===============================================================
2446 Function Get_Violat_Existing_Role_List (
2447     p_user_id                   IN  NUMBER,
2448     p_constraint_rev_id         IN  NUMBER,
2449     p_constraint_type_code      IN  VARCHAR2
2450 ) RETURN VARCHAR2
2451 IS
2452 L_API_NAME                  CONSTANT VARCHAR2(30) := 'Get_Violat_Existing_Role_List';
2453 L_API_VERSION_NUMBER        CONSTANT NUMBER		  := 1.0;
2454 
2455 -- store the return value
2456 l_existing_role_string VARCHAR2(32767);
2457 
2458 -- store the existing role this user has against this constraint
2459 l_existing_role_table JTF_VARCHAR2_TABLE_400;
2460 
2461 TYPE refCurTyp IS REF CURSOR;
2462 existing_role_c refCurTyp;
2463 
2464 -- find existing roles this user has (results in violating the specified constraint)
2465 l_existing_role_dynamic_sql   VARCHAR2(500)  :=
2466     'select distinct rv.display_name '
2467   ||'  from amw_role_constraint_denorm rcd '
2468   ||'      ,'||G_AMW_USER_ROLES||' ur '
2469   ||'      ,'||G_AMW_user||' u '
2470   ||'      ,'||G_AMW_ALL_ROLES_VL||' rv '
2471   ||'  where rcd.constraint_rev_id = :1 '
2472   ||'    and u.user_id = :2 '
2473   ||'    and u.user_name = ur.user_name '
2474   ||'    and ur.role_name = rcd.role_name '
2475   ||'    and ur.role_orig_system = ''UMX'' '
2476   ||'    and ur.role_name = rv.name ';
2477 
2478 BEGIN
2479   l_existing_role_string := NULL;
2480 
2481   IF (p_user_id IS NOT NULL AND p_constraint_rev_id IS NOT NULL AND p_constraint_type_code IS NOT NULL) THEN
2482     OPEN existing_role_c FOR l_existing_role_dynamic_sql USING
2483           p_constraint_rev_id,
2484           p_user_id;
2485     FETCH existing_role_c BULK COLLECT INTO l_existing_role_table;
2486     CLOSE existing_role_c;
2487 
2488     IF l_existing_role_table IS NOT NULL AND l_existing_role_table.FIRST IS NOT NULL THEN
2489       l_existing_role_string := l_existing_role_table(1);
2490       FOR i in 2 .. l_existing_role_table.COUNT
2491       LOOP
2492         l_existing_role_string := l_existing_role_string||', '||l_existing_role_table(i);
2493       END LOOP;
2494     END IF; -- end of if: l_existing_role_table IS NOT NULL
2495 
2496   END IF; --end of if: p_user_id IS NOT NULL AND p_constraint_rev_id IS NOT NULL AND p_constraint_type_code IS NOT NULL
2497 
2498   return l_existing_role_string;
2499 
2500 END Get_Violat_Existing_Role_List;
2501 
2502 
2503 
2504 
2505 -- ===============================================================
2506 -- Function name
2507 --          Get_Violat_Existing_Resp_List
2508 --
2509 -- Purpose
2510 --          get a flat string list of this user's existing responsibility display name, together with those new assigned role(among p_role_names_string)
2511 --          may violate the specified constraint
2512 --
2513 -- Params
2514 --          p_user_id            := input fnd user_id
2515 --          p_constraint_rev_id  := input constraint_rev_id
2516 --          p_constraint_type_code  := input constraint type for p_constraint_rev_id
2517 --
2518 -- Return
2519 --          a string list of role display names which violates the specified constraint,
2520 --          each display name is seperated by ','
2521 --
2522 -- History
2523 -- 		  	07/27/2005    tsho     Create
2524 -- ===============================================================
2525 Function Get_Violat_Existing_Resp_List (
2526     p_user_id                   IN  NUMBER,
2527     p_constraint_rev_id         IN  NUMBER,
2528     p_constraint_type_code      IN  VARCHAR2
2529 ) RETURN VARCHAR2
2530 IS
2531 L_API_NAME                  CONSTANT VARCHAR2(30) := 'Get_Violat_Existing_Resp_List';
2532 L_API_VERSION_NUMBER        CONSTANT NUMBER		  := 1.0;
2533 
2534 -- store the return value
2535 l_existing_resp_string VARCHAR2(32767);
2536 
2537 -- store the existing responsibilities this user has against this constraint
2538 l_existing_resp_table JTF_VARCHAR2_TABLE_400;
2539 
2540 TYPE refCurTyp IS REF CURSOR;
2541 existing_resp_c refCurTyp;
2542 
2543 -- find existing responsibilities this user has (results in violating the specified constraint)
2544 l_existing_resp_dynamic_sql   VARCHAR2(500)  :=
2545     'select distinct resp.responsibility_name '
2546   ||'  from amw_role_constraint_denorm rcd '
2547   ||'      ,'||G_AMW_USER_ROLES||' ur '
2548   ||'      ,'||G_AMW_user||' u '
2549   ||'      ,'||G_AMW_RESPONSIBILITY_VL||' resp '
2550   ||'  where rcd.constraint_rev_id = :1 '
2551   ||'    and u.user_id = :2 '
2552   ||'    and u.user_name = ur.user_name '
2553   ||'    and rcd.responsibility_id = resp.responsibility_id '
2554   ||'    and ur.role_orig_system_id = rcd.responsibility_id '
2555   ||'    and ur.role_orig_system = ''FND_RESP'' '
2556   ||'    and ur.role_orig_system_id = resp.responsibility_id ';
2557 
2558 BEGIN
2559   l_existing_resp_string := NULL;
2560 
2561   IF (p_user_id IS NOT NULL AND p_constraint_rev_id IS NOT NULL AND p_constraint_type_code IS NOT NULL) THEN
2562     OPEN existing_resp_c FOR l_existing_resp_dynamic_sql USING
2563           p_constraint_rev_id,
2564           p_user_id;
2565     FETCH existing_resp_c BULK COLLECT INTO l_existing_resp_table;
2566     CLOSE existing_resp_c;
2567 
2568     IF l_existing_resp_table IS NOT NULL AND l_existing_resp_table.FIRST IS NOT NULL THEN
2569       l_existing_resp_string := l_existing_resp_table(1);
2570       FOR i in 2 .. l_existing_resp_table.COUNT
2571       LOOP
2572         l_existing_resp_string := l_existing_resp_string||', '||l_existing_resp_table(i);
2573       END LOOP;
2574     END IF; -- end of if: l_existing_resp_table IS NOT NULL
2575 
2576   END IF; --end of if: p_user_id IS NOT NULL AND p_constraint_rev_id IS NOT NULL AND p_constraint_type_code IS NOT NULL
2577 
2578   return l_existing_resp_string;
2579 
2580 END Get_Violat_Existing_Resp_List;
2581 
2582 
2583 -- ===============================================================
2584 -- Function name
2585 --          Get_Violat_Existing_Menu_List
2586 --
2587 -- Purpose
2588 --          get a flat string list of this user's existing permission set(menu) display name, ]
2589 --          together with those new assigned role(among p_role_names_string)
2590 --          may violate the specified constraint
2591 --
2592 -- Params
2593 --          p_user_id            := input fnd user_id
2594 --          p_constraint_rev_id  := input constraint_rev_id
2595 --          p_constraint_type_code  := input constraint type for p_constraint_rev_id
2596 --
2597 -- Return
2598 --          a string list of role display names which violates the specified constraint,
2599 --          each display name is seperated by ','
2600 --
2601 -- History
2602 -- 		  	07/27/2005    tsho     Create
2603 -- ===============================================================
2604 Function Get_Violat_Existing_Menu_List (
2605     p_user_id                   IN  NUMBER,
2606     p_constraint_rev_id         IN  NUMBER,
2607     p_constraint_type_code      IN  VARCHAR2
2608 ) RETURN VARCHAR2
2609 IS
2610 L_API_NAME                  CONSTANT VARCHAR2(30) := 'Get_Violat_Existing_Menu_List';
2611 L_API_VERSION_NUMBER        CONSTANT NUMBER		  := 1.0;
2612 
2613 -- store the return value
2614 l_existing_menu_string VARCHAR2(32767);
2615 
2616 -- store the existing menus this user has against this constraint
2617 l_existing_menu_table JTF_VARCHAR2_TABLE_400;
2618 
2619 TYPE refCurTyp IS REF CURSOR;
2620 existing_menu_c refCurTyp;
2621 
2622 -- find existing menus this user has (results in violating the specified constraint)
2623 l_existing_menu_dynamic_sql   VARCHAR2(1500)  :=
2624     '  select menu.user_menu_name '
2625   ||'  from amw_role_constraint_denorm rcd '
2626   ||'      ,'||G_AMW_MENUS_VL||' menu '
2627   ||'      ,'||G_AMW_user||' u '
2628   ||'      ,'||G_AMW_GRANTS||' gra '
2629   ||'  where rcd.constraint_rev_id = :1 '
2630   ||'    and u.user_id = :2 '
2631   ||'    and u.user_name = gra.grantee_key '
2632   ||'    and gra.grantee_type = ''USER'' '
2633   ||'    and gra.instance_type = ''GLOBAL'' '
2634   ||'    and gra.object_id = -1 '
2635   ||'    and gra.menu_id = rcd.menu_id '
2636   ||'    and gra.menu_id = menu.menu_id '
2637   ||' UNION '
2638   ||'  select menu.user_menu_name '
2639   ||'  from amw_role_constraint_denorm rcd '
2640   ||'      ,'||G_AMW_MENUS_VL||' menu '
2641   ||'      ,'||G_AMW_GRANTS||' gra '
2642   ||'  where rcd.constraint_rev_id = :3 '
2643   ||'    and gra.grantee_key = ''GLOBAL'' '
2644   ||'    and gra.grantee_type = ''GLOBAL'' '
2645   ||'    and gra.instance_type = ''GLOBAL'' '
2646   ||'    and gra.object_id = -1 '
2647   ||'    and gra.menu_id = rcd.menu_id '
2648   ||'    and gra.menu_id = menu.menu_id ';
2649 
2650 BEGIN
2651   l_existing_menu_string := NULL;
2652 
2653   IF (p_user_id IS NOT NULL AND p_constraint_rev_id IS NOT NULL AND p_constraint_type_code IS NOT NULL) THEN
2654     OPEN existing_menu_c FOR l_existing_menu_dynamic_sql USING
2655           p_constraint_rev_id,
2656           p_user_id,
2657           p_constraint_rev_id;
2658     FETCH existing_menu_c BULK COLLECT INTO l_existing_menu_table;
2659     CLOSE existing_menu_c;
2660 
2661     IF l_existing_menu_table IS NOT NULL AND l_existing_menu_table.FIRST IS NOT NULL THEN
2662       l_existing_menu_string := l_existing_menu_table(1);
2663       FOR i in 2 .. l_existing_menu_table.COUNT
2664       LOOP
2665         l_existing_menu_string := l_existing_menu_string||', '||l_existing_menu_table(i);
2666       END LOOP;
2667     END IF; -- end of if: l_existing_menu_table IS NOT NULL
2668 
2669   END IF; --end of if: p_user_id IS NOT NULL AND p_constraint_rev_id IS NOT NULL AND p_constraint_type_code IS NOT NULL
2670 
2671   return l_existing_menu_string;
2672 
2673 END Get_Violat_Existing_Menu_List;
2674 
2675 
2676 -- ===============================================================
2677 -- Function name
2678 --          Get_Violat_Comments
2679 --
2680 -- Purpose
2681 --          get comments(instruction) for specified constraint_rev_id
2682 --
2683 -- Params
2684 --          p_constraint_rev_id  := input constraint_rev_id
2685 --          p_constraint_type_code  := input constraint type for p_constraint_rev_id
2686 --
2687 -- Return
2688 --          a seeded mesg
2689 --
2690 -- History
2691 -- 		  	07/27/2005    tsho     Create
2692 -- ===============================================================
2693 Function Get_Violat_Comments (
2694     p_constraint_rev_id         IN  NUMBER,
2695     p_constraint_type_code      IN  VARCHAR2
2696 ) RETURN VARCHAR2
2697 IS
2698 L_API_NAME                  CONSTANT VARCHAR2(30) := 'Get_Violat_Comments';
2699 L_API_VERSION_NUMBER        CONSTANT NUMBER		  := 1.0;
2700 
2701 -- store the return value
2702 l_violat_comments VARCHAR2(80);
2703 
2704 BEGIN
2705   l_violat_comments := NULL;
2706 
2707   IF p_constraint_type_code IS NOT NULL THEN
2708     IF p_constraint_type_code = 'ALL' THEN
2709       l_violat_comments := AMW_UTILITY_PVT.get_message_text('AMW_ROLE_VIOLAT_ALL_COMMENT');
2710     ELSE
2711       l_violat_comments := AMW_UTILITY_PVT.get_message_text('AMW_ROLE_VIOLAT_ME_COMMENT');
2712     END IF;
2713   END IF; -- end of if: p_constraint_type_code IS NOT NULL
2714 
2715   return l_Violat_Comments;
2716 
2717 END Get_Violat_Comments;
2718 
2719 
2720 -- ===============================================================
2721 -- Function name
2722 --          Do_On_Role_Assigned
2723 --
2724 -- Purpose
2725 --          listen to the worflow business event(mainly uses for oracle.apps.fnd.wf.ds.userRole.created)
2726 --          and do corresponding actions
2727 --
2728 -- Params
2729 --          p_subscription_guid
2730 --          p_event
2731 --
2732 -- Return
2733 --          'SUCCESS' | 'ERROR'
2734 --
2735 -- History
2736 -- 		  	07/29/2005    tsho     Create
2737 -- ===============================================================
2738 FUNCTION Do_On_Role_Assigned (
2739     p_subscription_guid   in     raw,
2740 	p_event               in out NOCOPY WF_EVENT_T
2741 ) return VARCHAR2
2742 IS
2743 L_API_NAME                  CONSTANT VARCHAR2(30) := 'Do_On_Role_Assigned';
2744 L_API_VERSION_NUMBER        CONSTANT NUMBER		  := 1.0;
2745 
2746 l_user_name	      VARCHAR2(100);
2747 l_role_name	      VARCHAR2(320);
2748 l_assigned_date   DATE;
2749 l_assigned_by_id  NUMBER;
2750 l_user_id	      VARCHAR2(100);
2751 
2752 TYPE curTyp IS REF CURSOR;
2753 c_user_dynamic_sql curTyp;
2754 l_user_dynamic_sql   VARCHAR2(200)  :=
2755         'SELECT u.user_id '
2756       ||'  FROM '||G_AMW_USER ||' u '
2757       ||' WHERE u.user_name = :1  ';
2758 
2759 BEGIN
2760     SAVEPOINT Do_On_Role_Assigned;
2761 
2762     IF p_event.EVENT_NAME = 'oracle.apps.fnd.umx.requestapproved' THEN
2763         -- This event is raised when a a role is assigned to a user.
2764         l_user_id   := p_event.GetValueForParameter('REQUESTED_FOR_USER_ID');
2765         l_role_name := p_event.GetValueForParameter('WF_ROLE_NAME');
2766         l_assigned_by_id := p_event.GetValueForParameter('REQUESTED_BY_USER_ID');
2767 
2768     ELSE
2769         -- This event is raised when a assigned role is updated.
2770         l_user_name := p_event.GetValueForParameter('USER_NAME');
2771         l_role_name := p_event.GetValueForParameter('ROLE_NAME');
2772         l_assigned_by_id := p_event.GetValueForParameter('CREATED_BY');
2773 
2774         OPEN c_user_dynamic_sql FOR l_user_dynamic_sql USING
2775              l_user_name;
2776         FETCH c_user_dynamic_sql INTO l_user_id;
2777         CLOSE c_user_dynamic_sql;
2778 
2779     END IF;
2780 
2781     IF l_user_id IS NOT NULL AND l_role_name IS NOT NULL THEN
2782         Send_Notif_To_Affected_Process(p_user_id     => l_user_id,
2783                                        p_role_name      => l_role_name,
2784                                        p_assigned_by_id => l_assigned_by_id);
2785      -- updated by dliao on 7-31-06 because the role_name could be null for the user
2786      -- registration (bug 5396917)
2787      -- Return 'SUCCESS';
2788     END IF;
2789 
2790     Return 'SUCCESS';
2791 
2792 EXCEPTION
2793   WHEN OTHERS  THEN
2794      ROLLBACK TO Do_On_Role_Assigned;
2795      FND_MESSAGE.SET_NAME( 'AMW', 'GENERIC_MESSAGE' );
2796      FND_MESSAGE.SET_TOKEN( 'GENERIC_TEXT' ,SQLERRM );
2797      FND_MSG_PUB.ADD;
2798 
2799      WF_CORE.CONTEXT('AMW_VIOLATION_PVT','Do_On_Role_Assigned error', p_event.getEventName(), p_subscription_guid);
2800      WF_EVENT.setErrorInfo(p_event,'ERROR');
2801      RETURN 'ERROR';
2802 END Do_On_Role_Assigned;
2803 
2804 
2805 -- ===============================================================
2806 -- Procedure name
2807 --          Send_Notif_To_Affected_Process
2808 --
2809 -- Purpose
2810 --          send violation notification to affected process owners
2811 --          it'll find which constraints have been violated due to the user role assignment
2812 --          and send notification to each process owner of those constraints
2813 -- Params
2814 --          p_item_type       := worflow template (default : AMWNOTIF)
2815 --          p_message_name    := workflow mesg template (default : MWVIOLATUSERROLENOTIF)
2816 --          p_user_name       := the user who got the role assigned
2817 --          p_role_name       := the new role which is assigned to this user
2818 --          p_assigned_date   := the assigned date
2819 --          p_assigned_by_id  := the role is assigned by which user (user_id)
2820 --
2821 -- History
2822 -- 		  	07/29/2005    tsho     Create
2823 --          02/23/2006    psomanat removied the parameter p_user_name
2824 --          02/23/2006    psomanat added the parameter p_user_id
2825 -- ===============================================================
2826 Procedure Send_Notif_To_Affected_Process(
2827     p_item_type      IN VARCHAR2 := 'AMWNOTIF',
2828 	p_message_name   IN VARCHAR2 := 'VIOLATIONNOTIF',
2829     p_user_id        IN NUMBER,
2830     p_role_name      IN VARCHAR2,
2831     p_assigned_by_id IN NUMBER
2832 )
2833 IS
2834 L_API_NAME                  CONSTANT VARCHAR2(30) := 'Send_Notif_To_Affected_Process';
2835 L_API_VERSION_NUMBER        CONSTANT NUMBER		  := 1.0;
2836 
2837 l_return_status   varchar2(30);
2838 
2839 -- store the result of l_violated_cst_dynamic_sql
2840 violated_cst_rev_id_list G_NUMBER_TABLE;
2841 new_role_list G_VARCHAR2_LONG_TABLE;
2842 
2843 -- store the result of C_Proc_Owner
2844 affected_proc_owner_id_list G_NUMBER_TABLE;
2845 
2846 -- store the result of C_Controls_Ids
2847 associated_cont_ids_list G_NUMBER_TABLE;
2848 TYPE curTyp IS REF CURSOR;
2849 -- get violated constraint for specified p_user_name and newly assigned p_role_name
2850 c_violated_cst_dynamic_sql curTyp;
2851 l_violated_cst_dynamic_sql   VARCHAR2(32767) :=
2852    'select * from ( '
2853    -- ALL
2854  ||' select AMW_VIOLATION_PVT.get_violat_new_role_list(:1,cst.constraint_rev_id,cst.type_code,:2) NEW_ROLE '
2855  ||'       ,cst.constraint_rev_id '
2856  ||' from amw_constraints_b cst '
2857  ||' where cst.type_code = ''ALL'' '
2858  ||'   and cst.start_date <= sysdate AND (cst.end_date IS NULL OR cst.end_date >= sysdate) '
2859  ||'   and (select count(*) '
2860  ||'        from amw_constraint_entries ce '
2861  ||'        where ce.constraint_rev_id = cst.constraint_rev_id) = ( '
2862  ||' select count(distinct rcd.function_id) '
2863  ||' from amw_role_constraint_denorm rcd '
2864  ||' where rcd.constraint_rev_id = cst.constraint_rev_id '
2865  ||'   and ( rcd.role_name = :3 '
2866  ||'      or (rcd.role_name in ( '
2867  ||'          select ur.role_name '
2868  ||'          from '||G_AMW_USER_ROLES||' ur '
2869  ||'              ,'||G_AMW_USER||' u '
2870  ||'          where u.user_id = :4 '
2871  ||'            and u.user_name = ur.user_name '
2872  ||'            and ur.role_orig_system = ''UMX'') '
2873  ||'          ) '
2874  ||'      or (rcd.responsibility_id in ( '
2875  ||'          select ur.role_orig_system_id '
2876  ||'          from '||G_AMW_USER_ROLES||' ur '
2877  ||'              ,'||G_AMW_USER||' u '
2878  ||'          where u.user_id = :5 '
2879  ||'            and u.user_name = ur.user_name '
2880  ||'            and ur.role_orig_system = ''FND_RESP'') '
2881  ||'          ) '
2882  ||'       or (rcd.menu_id in ( '
2883  ||'           select gra.menu_id '
2884  ||'           from '||G_AMW_GRANTS||' gra '
2885  ||'               ,'||G_AMW_USER||' u '
2886  ||'           where u.user_id = :6 '
2887  ||'             and u.user_name = gra.grantee_key '
2888  ||'             and gra.grantee_type = ''USER'' '
2889  ||'             and gra.instance_type = ''GLOBAL'' '
2890  ||'             and gra.object_id = -1) '
2891  ||'           ) '
2892  ||'       or (rcd.menu_id in ( '
2893  ||'           select gra.menu_id '
2894  ||'           from '||G_AMW_GRANTS||' gra '
2895  ||'           where gra.grantee_key = ''GLOBAL'' '
2896  ||'             and gra.grantee_type = ''GLOBAL'' '
2897  ||'             and gra.instance_type = ''GLOBAL'' '
2898  ||'             and gra.object_id = -1) '
2899  ||'           ) '
2900  ||'   ) '
2901  ||' ) '
2902  ||' UNION ALL '
2903  -- ME
2904  ||' select AMW_VIOLATION_PVT.get_violat_new_role_list(:7,cst.constraint_rev_id,cst.type_code,:8) NEW_ROLE '
2905  ||'      , cst.constraint_rev_id '
2906  ||' from amw_constraints_b cst '
2907  ||' where cst.type_code = ''ME'' '
2908  ||'   and cst.start_date <= sysdate AND (cst.end_date IS NULL OR cst.end_date >= sysdate) '
2909  ||'   and (select count(distinct rcd.function_id) '
2910  ||'        from amw_role_constraint_denorm rcd '
2911  ||'        where rcd.constraint_rev_id = cst.constraint_rev_id '
2912  ||'          and ( rcd.role_name = :9 '
2913  ||'             or (rcd.role_name in ( '
2914  ||'                 select ur.role_name '
2915  ||'                 from '||G_AMW_USER_ROLES||' ur '
2916  ||'                     ,'||G_AMW_USER||' u '
2917  ||'                 where u.user_id = :10 '
2918  ||'                   and u.user_name = ur.user_name '
2919  ||'                   and ur.role_orig_system = ''UMX'') '
2920  ||'                 ) '
2921  ||'             or (rcd.responsibility_id in ( '
2922  ||'                 select ur.role_orig_system_id '
2923  ||'                 from '||G_AMW_USER_ROLES||' ur '
2924  ||'                     ,'||G_AMW_USER||' u '
2925  ||'                 where u.user_id = :11 '
2926  ||'                   and u.user_name = ur.user_name '
2927  ||'                   and ur.role_orig_system = ''FND_RESP'') '
2928  ||'                 ) '
2929  ||'             or (rcd.menu_id in ( '
2930  ||'                 select gra.menu_id '
2931  ||'                 from '||G_AMW_GRANTS||' gra '
2932  ||'                     ,'||G_AMW_USER||' u '
2933  ||'                 where u.user_id = :12 '
2934  ||'                   and u.user_name = gra.grantee_key '
2935  ||'                   and gra.grantee_type = ''USER'' '
2936  ||'                   and gra.instance_type = ''GLOBAL'' '
2937  ||'                   and gra.object_id = -1) '
2938  ||'                 ) '
2939  ||'              or (rcd.menu_id in ( '
2940  ||'                  select gra.menu_id '
2941  ||'                  from '||G_AMW_GRANTS||' gra '
2942  ||'                  where gra.grantee_key = ''GLOBAL'' '
2943  ||'                    and gra.grantee_type = ''GLOBAL'' '
2944  ||'                    and gra.instance_type = ''GLOBAL'' '
2945  ||'                    and gra.object_id = -1) '
2946  ||'                  ) '
2947  ||'          ) '
2948  ||'       ) >= 2 '
2949  ||' UNION ALL '
2950  -- SET
2951  ||' select AMW_VIOLATION_PVT.get_violat_new_role_list(:13,cst.constraint_rev_id,cst.type_code,:14) NEW_ROLE '
2952  ||'       ,cst.constraint_rev_id '
2953  ||' from amw_constraints_b cst '
2954  ||' where cst.type_code = ''SET'' '
2955  ||'   and cst.start_date <= sysdate AND (cst.end_date IS NULL OR cst.end_date >= sysdate) '
2956  ||'   and (select count(distinct rcd.group_code) '
2957  ||'        from amw_role_constraint_denorm rcd '
2958  ||'        where rcd.constraint_rev_id = cst.constraint_rev_id '
2959  ||'          and (rcd.role_name = :15 '
2960  ||'            or (rcd.role_name in ( '
2961  ||'                select ur.role_name '
2962  ||'                from '||G_AMW_USER_ROLES||' ur '
2963  ||'                    ,'||G_AMW_USER||' u '
2964  ||'                where u.user_id = :16 '
2965  ||'                  and u.user_name = ur.user_name '
2966  ||'                  and ur.role_orig_system = ''UMX'') '
2967  ||'               ) '
2968  ||'            or (rcd.responsibility_id in ( '
2969  ||'                select ur.role_orig_system_id '
2970  ||'                from '||G_AMW_USER_ROLES||' ur '
2971  ||'                    ,'||G_AMW_USER||' u '
2972  ||'                where u.user_id = :17 '
2973  ||'                  and u.user_name = ur.user_name '
2974  ||'                  and ur.role_orig_system = ''FND_RESP'') '
2975  ||'               ) '
2976  ||'            or (rcd.menu_id in ( '
2977  ||'                select gra.menu_id '
2978  ||'                from '||G_AMW_GRANTS||' gra '
2979  ||'                    ,'||G_AMW_USER||' u '
2980  ||'                where u.user_id = :18 '
2981  ||'                  and u.user_name = gra.grantee_key '
2982  ||'                  and gra.grantee_type = ''USER'' '
2983  ||'                  and gra.instance_type = ''GLOBAL'' '
2984  ||'                  and gra.object_id = -1) '
2985  ||'               ) '
2986  ||'            or (rcd.menu_id in ( '
2987  ||'                select gra.menu_id '
2988  ||'                from '||G_AMW_GRANTS||' gra '
2989  ||'                where gra.grantee_key = ''GLOBAL'' '
2990  ||'                  and gra.grantee_type = ''GLOBAL'' '
2991  ||'                  and gra.instance_type = ''GLOBAL'' '
2992  ||'                  and gra.object_id = -1) '
2993  ||'               ) '
2994  ||'          ) '
2995  ||'       ) >= 2 '
2996  ||' UNION ALL '
2997    -- RESPALL
2998  ||' select AMW_VIOLATION_PVT.get_violat_new_role_list(:19,cst.constraint_rev_id,cst.type_code,:20) NEW_ROLE '
2999  ||'       ,cst.constraint_rev_id '
3000  ||' from amw_constraints_b cst '
3001  ||' where cst.type_code = ''RESPALL'' '
3002  ||'   and cst.start_date <= sysdate AND (cst.end_date IS NULL OR cst.end_date >= sysdate) '
3003  ||'   and (select count(*) '
3004  ||'        from amw_constraint_entries ce '
3005  ||'        where ce.constraint_rev_id = cst.constraint_rev_id) = ( '
3006  ||        '  select count(distinct ur.role_orig_system_id) '
3007  ||'  from '
3008  || G_AMW_USER_ROLES||' ur '
3009  ||'      ,'||G_AMW_user||' u '
3010  ||'      ,amw_constraint_entries ce '
3011  ||'  where  u.user_id = :21 '
3012  ||'    and  ce.constraint_rev_id = cst.constraint_rev_id '
3013  ||'    and u.user_name = ur.user_name '
3014  ||'    and ur.role_orig_system_id = ce.function_id '
3015  ||'    and (ur.role_orig_system = ''FND_RESP'' '
3016  ||'    or ur.role_orig_system_id in ( '
3017  ||'  select distinct rle.orig_system_id '
3018  ||'  from  ' || G_AMW_ALL_ROLES_VL || ' rle '
3019  ||'  where rle.orig_system = ''FND_RESP'' '
3020  ||'  and ce.function_id = rle.orig_system_id '
3021  ||'  and rle.name in (:22)) '
3022  ||') '
3023  || ') '
3024  ||' UNION ALL '
3025    -- RESPME
3026   ||' select AMW_VIOLATION_PVT.get_violat_new_role_list(:23,cst.constraint_rev_id,cst.type_code,:24) NEW_ROLE '
3027  ||'      , cst.constraint_rev_id '
3028  ||' from amw_constraints_b cst '
3029  ||' where cst.type_code = ''RESPME'' '
3030  ||'   and cst.start_date <= sysdate AND (cst.end_date IS NULL OR cst.end_date >= sysdate) '
3031  ||'   and '
3032  || '  (select count(distinct ur.role_orig_system_id ) '
3033  ||'  from '
3034  || G_AMW_USER_ROLES||' ur '
3035  ||'      ,'||G_AMW_user||' u '
3036  ||'      ,amw_constraint_entries ce '
3037  ||'  where  u.user_id = :25 '
3038  ||'    and  ce.constraint_rev_id = cst.constraint_rev_id '
3039  ||'    and u.user_name = ur.user_name '
3040  ||'    and ur.role_orig_system_id = ce.function_id '
3041  ||'    and (ur.role_orig_system = ''FND_RESP'' '
3042  ||'    or ur.role_orig_system_id in ( '
3043  ||'  select distinct rle.orig_system_id '
3044  ||'  from  ' || G_AMW_ALL_ROLES_VL || ' rle '
3045  ||'  where rle.orig_system = ''FND_RESP'' '
3046  ||'  and ce.function_id = rle.orig_system_id '
3047  ||'  and rle.name in (:26 )) '
3048  ||') '
3049  ||') '
3050  ||' >= 2 '
3051  ||' UNION ALL '
3052  -- RESPSET
3053   ||' select AMW_VIOLATION_PVT.get_violat_new_role_list(:27,cst.constraint_rev_id,cst.type_code,:28) NEW_ROLE '
3054  ||'      , cst.constraint_rev_id '
3055  ||' from amw_constraints_b cst '
3056  ||' where cst.type_code = ''RESPME'' '
3057  ||'   and cst.start_date <= sysdate AND (cst.end_date IS NULL OR cst.end_date >= sysdate) '
3058  ||'   and '
3059  || '  (select count(distinct ur.role_orig_system_id ) '
3060  ||'  from '
3061  || G_AMW_USER_ROLES||' ur '
3062  ||'      ,'||G_AMW_user||' u '
3063  ||'      ,amw_constraint_entries ce '
3064  ||'  where  u.user_id = :29 '
3065  ||'    and  ce.constraint_rev_id = cst.constraint_rev_id '
3066  ||'    and u.user_name = ur.user_name '
3067  ||'    and ur.role_orig_system_id = ce.function_id '
3068  ||'    and (ur.role_orig_system = ''FND_RESP'' '
3069  ||'    or ur.role_orig_system_id in ( '
3070  ||'  select distinct rle.orig_system_id '
3071  ||'  from  ' || G_AMW_ALL_ROLES_VL || ' rle '
3072  ||'  where rle.orig_system = ''FND_RESP'' '
3073  ||'  and ce.function_id = rle.orig_system_id '
3074  ||'  and rle.name in (:30 )) '
3075  ||') '
3076  ||') '
3077  ||' >= 2 '
3078   ||' ) where NEW_ROLE IS NOT NULL ';
3079 
3080 --27:12:05 : psomanat
3081 -- holds the control associated with the Constraint
3082 CURSOR C_Control_Ids(l_constraint_id in NUMBER) IS
3083 SELECT CONTROL_ID
3084           FROM AMW_CONTROLS_ALL_VL ctl
3085           WHERE ctl.AUTOMATION_TYPE ='SOD'
3086             AND CURR_APPROVED_FLAG ='Y'
3087             AND ctl.SOURCE =l_constraint_id;
3088 
3089 -- Store the Constraint id for the given constraint revision id.
3090 l_constraint_id number;
3091 
3092 --27:12:05 : psomanat
3093 -- A Control is associated a Constraint. So get the process owners of all the process
3094 -- that uses this control to mitigate the associated risk.
3095 CURSOR C_Proc_Owner(l_cont_id in NUMBER) IS
3096 SELECT distinct TO_NUMBER(REPLACE(grants.grantee_key,'HZ_PARTY:','')) party_id
3097 FROM AMW_control_Associations ca,
3098      fnd_grants grants,
3099      fnd_menus granted_menu,
3100      fnd_objects obj
3101 WHERE   CONTROL_ID = l_cont_id
3102    AND  OBJECT_TYPE ='RISK'
3103    AND  APPROVAL_DATE IS NOT NULL
3104    AND  DELETION_APPROVAL_DATE IS NULL
3105    and obj.obj_name = 'AMW_PROCESS_APPR_ETTY'
3106    AND grants.object_id = obj.object_id
3107    AND   grants.grantee_type ='USER'
3108    AND   grantee_key like 'HZ_PARTY%'
3109    AND   NVL(grants.end_date, SYSDATE+1) >= TRUNC(SYSDATE)
3110    AND   grants.menu_id = granted_menu.menu_id
3111    AND   grants.instance_type = 'INSTANCE'
3112    AND   grants.instance_pk1_value = TO_CHAR(ca.PK1)
3113    AND   grants.instance_pk2_value = '*NULL*'
3114    AND   grants.instance_pk3_value = '*NULL*'
3115    AND   grants.instance_pk4_value = '*NULL*'
3116    AND   grants.instance_pk5_value = '*NULL*'
3117    AND   granted_menu.menu_name =  'AMW_RL_PROC_OWNER_ROLE'
3118    UNION
3119    SELECT   distinct TO_NUMBER(REPLACE(grants.grantee_key,'HZ_PARTY:','')) party_id
3120     FROM    AMW_control_Associations ca,
3121             fnd_grants grants,
3122             fnd_menus granted_menu,
3123             fnd_objects obj
3124     WHERE CONTROL_ID = l_cont_id
3125         AND  OBJECT_TYPE ='RISK_ORG'
3126         AND  APPROVAL_DATE IS NOT NULL
3127         AND  DELETION_APPROVAL_DATE IS NULL
3128         AND  obj.obj_name = 'AMW_PROCESS_ORGANIZATION'
3129         AND   grants.object_id = obj.object_id
3130         AND   grants.grantee_type ='USER'
3131         AND   grantee_key like 'HZ_PARTY%'
3132         AND   NVL(grants.end_date, SYSDATE+1) >= TRUNC(SYSDATE)
3133         AND   grants.menu_id = granted_menu.menu_id
3134         AND   grants.instance_type = 'INSTANCE'
3135         AND   grants.instance_pk1_value = to_char(ca.pk1)      -- PASS ORG_ID AS STRING
3136         AND   grants.instance_pk2_value = to_char(ca.pk2)      -- PASS PROCESS_ID AS STRING I.E. to_char(process_id)
3137         AND   grants.instance_pk3_value = '*NULL*'
3138         AND   grants.instance_pk4_value = '*NULL*'
3139         AND   grants.instance_pk5_value = '*NULL*'
3140         and   granted_menu.menu_name = 'AMW_ORG_PROC_OWNER_ROLE';
3141 
3142 BEGIN
3143     l_return_status := FND_API.G_RET_STS_SUCCESS;
3144 
3145     IF (p_user_id IS NULL or p_role_name IS NULL) THEN
3146         RETURN;
3147     END IF;
3148 
3149     -- get list of violated constraint id
3150     OPEN c_violated_cst_dynamic_sql FOR l_violated_cst_dynamic_sql USING
3151         -- ALL
3152         p_user_id
3153         ,p_role_name
3154         ,p_role_name
3155         ,p_user_id
3156         ,p_user_id
3157         ,p_user_id
3158         -- ME
3159         ,p_user_id
3160         ,p_role_name
3161         ,p_role_name
3162         ,p_user_id
3163         ,p_user_id
3164         ,p_user_id
3165         -- SET
3166         ,p_user_id
3167         ,p_role_name
3168         ,p_role_name
3169         ,p_user_id
3170         ,p_user_id
3171         ,p_user_id
3172         -- RESPALL
3173         ,p_user_id
3174         ,p_role_name
3175         ,p_user_id
3176         ,p_role_name
3177         --RESPME
3178         ,p_user_id
3179         ,p_role_name
3180         ,p_user_id
3181         ,p_role_name
3182         --RESPSET
3183         ,p_user_id
3184         ,p_role_name
3185         ,p_user_id
3186         ,p_role_name
3187         ;
3188     FETCH c_violated_cst_dynamic_sql BULK COLLECT INTO new_role_list, violated_cst_rev_id_list;
3189     CLOSE c_violated_cst_dynamic_sql;
3190 
3191     IF violated_cst_rev_id_list IS NULL OR NOT violated_cst_rev_id_list.exists(1) THEN
3192         RETURN;
3193     END IF;
3194 
3195     FOR i in 1 .. violated_cst_rev_id_list.COUNT
3196     LOOP
3197         -- The Constraint _id is associated to the control. So we get the
3198         --Constraint _id corresponding to the violated constraint_rev_id
3199         SELECT  constraint_id into l_constraint_id
3200         FROM    AMW_CONSTRAINTS_VL
3201         WHERE   constraint_rev_id=violated_cst_rev_id_list(i);
3202 
3203         -- A constraint can be associate to many controls. So we get the all
3204         -- the constrols with source as the constraint.
3205         OPEN C_Control_Ids(l_constraint_id);
3206         FETCH C_Control_Ids BULK COLLECT INTO associated_cont_ids_list;
3207         CLOSE C_Control_Ids;
3208 
3209         -- For each control we find the affected process owner
3210         -- and send notification to them
3211         FOR k IN 1 .. associated_cont_ids_list.COUNT
3212         LOOP
3213             -- get all the affected process owners
3214             OPEN C_Proc_Owner(associated_cont_ids_list(k));
3215             FETCH C_Proc_Owner BULK COLLECT INTO affected_proc_owner_id_list;
3216             CLOSE C_Proc_Owner;
3217 
3218             IF affected_proc_owner_id_list IS NOT NULL THEN
3219                 FOR j in 1 ..affected_proc_owner_id_list.COUNT
3220                 LOOP
3221                     IF affected_proc_owner_id_list(j) IS NOT NULL THEN
3222                         Send_Notif_To_Process_Owner(
3223                             p_item_type         => p_item_type,
3224             	            p_message_name      => p_message_name,
3225                             p_user_id           => p_user_id,
3226                             p_role_name         => p_role_name,
3227                             p_assigned_by_id    => p_assigned_by_id,
3228                             p_constraint_rev_id => violated_cst_rev_id_list(i),
3229                             p_process_owner_id  => affected_proc_owner_id_list(j),
3230                             x_return_status     => l_return_status);
3231                     END IF;--end of if: affected_proc_owner_id_list(j) IS NOT NULL
3232                 END LOOP; -- end of for: affected_proc_owner_id_list.COUNT
3233             END IF; --end of if: affected_proc_owner_id_list IS NOT NULL
3234         END LOOP; --end of for :associated_cont_ids_list.COUNT
3235     END LOOP; --end of for: violated_cst_rev_id_list.COUNT
3236 EXCEPTION
3237    WHEN OTHERS THEN
3238       fnd_file.put_line(fnd_file.LOG,'unexpected error in Send_Notif_To_Affected_Process: '||sqlerrm);
3239       l_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
3240 END Send_Notif_To_Affected_Process;
3241 
3242 -- ===============================================================
3243 -- Procedure name
3244 --          Send_Notif_To_Process_Owner
3245 --
3246 -- Purpose
3247 --          send violation notification to specified process owner
3248 -- Params
3249 --          p_item_type       := worflow template (default : AMWNOTIF)
3250 --          p_message_name    := workflow mesg template (default : MWVIOLATUSERROLENOTIF)
3251 --          p_user_name       := the user who got the role assigned
3252 --          p_role_name       := the new role which is assigned to this user
3253 --          p_assigned_date   := the assigned date
3254 --          p_assigned_by_id  := the role is assigned by which user (user_id)
3255 --          p_constraint_rev_id   := which constraint has been violated
3256 --          p_process_owner_id    := the process owner of that constraint, to whom this notif will be sent
3257 --
3258 -- History
3259 -- 		  	07/29/2005    tsho     Create
3260 --          02/23/2006    psomanat removied the parameter p_user_name
3261 --          02/23/2006    psomanat added the parameter p_user_id
3262 -- ===============================================================
3263 Procedure Send_Notif_To_Process_Owner(
3264     p_item_type           IN VARCHAR2 := 'AMWNOTIF',
3265 	p_message_name        IN VARCHAR2 := 'VIOLATIONNOTIF',
3266     p_user_id             IN NUMBER,
3267     p_role_name           IN VARCHAR2,
3268     p_assigned_by_id      IN NUMBER,
3269     p_constraint_rev_id   IN NUMBER,
3270     p_process_owner_id    IN NUMBER,
3271     x_return_status       OUT NOCOPY VARCHAR2
3272 )
3273 IS
3274 L_API_NAME                  CONSTANT VARCHAR2(30) := 'Send_Notif_To_Process_Owner';
3275 L_API_VERSION_NUMBER        CONSTANT NUMBER		  := 1.0;
3276 
3277     l_constraint_name    VARCHAR2(240);
3278     l_to_role_name       VARCHAR2(100);
3279     l_display_role_name	 VARCHAR2(320);
3280     l_subject		     VARCHAR2(2000);
3281     l_user_name		     Varchar2(240);
3282     l_role_name          VARCHAR2(320) :=p_role_name;
3283     l_assigned_by_id     NUMBER :=p_assigned_by_id;
3284     l_notif_id		     NUMBER;
3285     emp_id_list          G_NUMBER_TABLE;
3286 
3287     cursor c_constraint (l_constraint_rev_id NUMBER) is
3288        select constraint_name
3289        from   amw_constraints_vl
3290        where  constraint_rev_id = l_constraint_rev_id;
3291 
3292     cursor c_person (c_party_id NUMBER) is
3293        select employee_id
3294        from   amw_employees_current_v
3295        where  party_id = c_party_id;
3296 
3297     TYPE curTyp IS REF CURSOR;
3298     c_user_dynamic_sql curTyp;
3299     l_user_dynamic_sql   VARCHAR2(200)  :=
3300             'SELECT u.user_name '
3301           ||'  FROM '||G_AMW_USER ||' u '
3302           ||' WHERE u.user_id = :1  ';
3303 BEGIN
3304     x_return_status := FND_API.G_RET_STS_SUCCESS;
3305 
3306     open c_constraint(p_constraint_rev_id);
3307     fetch c_constraint into l_constraint_name;
3308     close c_constraint;
3309 
3310     open c_person(p_process_owner_id);
3311     fetch c_person bulk collect into emp_id_list;
3312     close c_person;
3313 
3314     FOR i in 1 .. emp_id_list.COUNT
3315     LOOP
3316         l_to_role_name:=NULL;
3317 
3318         WF_DIRECTORY.getrolename(   p_orig_system      => 'PER',
3319 	                                p_orig_system_id   => emp_id_list(i),
3320                                     p_name             => l_to_role_name,
3321                                     p_display_name     => l_display_role_name );
3322 
3323         IF l_to_role_name IS NULL THEN
3324 
3325             x_return_status := FND_API.G_RET_STS_ERROR;
3326             FND_MESSAGE.set_name('AMW','AMW_APPR_INVALID_ROLE');
3327             FND_MSG_PUB.ADD;
3328             fnd_file.put_line(fnd_file.LOG, 'to_role is null');
3329         ELSE
3330 
3331             OPEN c_user_dynamic_sql FOR l_user_dynamic_sql USING
3332                 p_user_id;
3333             FETCH c_user_dynamic_sql INTO l_user_name;
3334             CLOSE c_user_dynamic_sql;
3335 
3336             FND_MESSAGE.set_name('AMW', 'AMW_VIOLAT_CONFIRM_NOTIF_SUBJ');
3337             FND_MESSAGE.set_token('CONSTRAINT_NAME', l_constraint_name, TRUE);
3338             FND_MESSAGE.set_token('USER_NAME', l_user_name, TRUE);
3339             FND_MSG_PUB.add;
3340             l_subject := fnd_msg_pub.get(p_msg_index => fnd_msg_pub.G_LAST,
3341 				                         p_encoded => fnd_api.g_false);
3342 
3343             l_notif_id := WF_NOTIFICATION.send(
3344                 role => l_to_role_name,
3345 			     msg_type => p_item_type,
3346 			     msg_name => p_message_name);
3347 
3348             WF_NOTIFICATION.SetAttrText(l_notif_id,'VN_MSG_SUBJECT',l_subject);
3349             WF_NOTIFICATION.setattrnumber(l_notif_id,'VN_CONSTRAINT_REV_ID',p_constraint_rev_id);
3350             WF_NOTIFICATION.SetAttrText(l_notif_id,'VN_ROLE_NAME',l_role_name);
3351             WF_NOTIFICATION.setattrnumber(l_notif_id,'VN_USER_ID',p_user_id);
3352             WF_NOTIFICATION.setattrnumber(l_notif_id,'VN_ASSIGNED_BY_ID',l_assigned_by_id);
3353 
3354         END IF; --end of if: l_to_role_name IS NULL
3355     END LOOP; --end of for: emp_id_list.COUNT
3356 EXCEPTION
3357    WHEN OTHERS THEN
3358       fnd_file.put_line(fnd_file.LOG,'unexpected error in Send_Notif_To_Process_Owner: '||sqlerrm);
3359       x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
3360 END;
3361 
3362 
3363 -- ===============================================================
3364 -- Function name
3365 --          Violation_Detail_Due_To_Resp
3366 --
3367 -- Purpose
3368 --          check for OICM SOD constriants that will be violated
3369 --          if the user is assigned the additional responsibility
3370 -- Params
3371 --          p_user_id            := input fnd user_id
3372 --          p_responsibility_id  := input fnd responsibility_id
3373 -- Return
3374 --          'N'                            := if no SOD violation found.
3375 --          'ConstraintName:Resp_name1;Resp_name2;...'    := if SOD violation exists.
3376 --                                            The SOD violation should NOT be restricted to
3377 --                                            only the new responsiblity.
3378 --                                            If the existing responsibilities have any violations,
3379 --                                            the function should return 'Y' as well.
3380 --
3381 -- History
3382 -- 		  	08/01/2005    tsho     Create
3383 --          08/03/2005    tsho     Consider User Waivers
3384 --          08/22/2005    tsho     Consider only prevent(PR) constraint objective
3385 -- ===============================================================
3386 Function Violation_Detail_Due_To_Resp (
3387     p_user_id               IN  NUMBER,
3388     p_responsibility_id     IN  NUMBER
3389 ) return VARCHAR2
3390 IS
3391 
3392 L_API_NAME                  CONSTANT VARCHAR2(30) := 'Violation_Detail_Due_To_Resp';
3393 L_API_VERSION_NUMBER        CONSTANT NUMBER		  := 1.0;
3394 
3395 -- return result
3396 has_violation VARCHAR2(32767);
3397 l_violat_existing_resp VARCHAR2(10000);
3398 l_violat_existing_role VARCHAR2(10000);
3399 l_violat_existing_menu VARCHAR2(10000);
3400 l_violat_new_resp VARCHAR2(100);
3401 
3402 -- find all valid constraints
3403 CURSOR c_all_valid_constraints IS
3404       SELECT constraint_rev_id, type_code, constraint_name, objective_code
3405         FROM amw_constraints_vl
3406        WHERE start_date <= sysdate AND (end_date IS NULL OR end_date >= sysdate);
3407 l_all_valid_constraints c_all_valid_constraints%ROWTYPE;
3408 
3409 -- find the number of constraint entries(incompatible functions) by specified constraint_rev_id
3410 l_constraint_entries_count NUMBER;
3411 l_func_access_count NUMBER;
3412 l_group_access_count NUMBER;
3413 CURSOR c_constraint_entries_count (l_constraint_rev_id IN NUMBER) IS
3414       SELECT count(*)
3415         FROM amw_constraint_entries
3416 	   WHERE constraint_rev_id=l_constraint_rev_id;
3417 
3418 
3419 TYPE refCurTyp IS REF CURSOR;
3420 func_acess_count_c refCurTyp;
3421 group_acess_count_c refCurTyp;
3422 
3423 l_func_dynamic_sql   VARCHAR2(2500)  :=
3424     'select count(distinct function_id) from ( '
3425   ||'  select rcd.function_id '
3426   ||'  from amw_role_constraint_denorm rcd '
3427   ||'      ,'||G_AMW_USER_ROLES||' ur '
3428   ||'      ,'||G_AMW_user||' u '
3429   ||'  where rcd.constraint_rev_id = :1 '
3430   ||'    and u.user_id = :2 '
3431   ||'    and u.user_name = ur.user_name '
3432   ||'    and ur.role_name = rcd.role_name '
3433   ||'    and ur.role_orig_system = ''UMX'' '
3434   ||'  UNION ALL '
3435   ||'  select rcd.function_id '
3436   ||'  from amw_role_constraint_denorm rcd '
3437   ||'      ,'||G_AMW_USER_ROLES||' ur '
3438   ||'      ,'||G_AMW_user||' u '
3439   ||'  where rcd.constraint_rev_id = :3 '
3440   ||'    and u.user_id = :4 '
3441   ||'    and u.user_name = ur.user_name '
3442   ||'    and ur.role_orig_system_id = rcd.responsibility_id '
3443   ||'    and ur.role_orig_system = ''FND_RESP'' '
3444   ||'  UNION ALL '
3445   ||'  select rcd.function_id '
3446   ||'  from amw_role_constraint_denorm rcd '
3447   ||'      ,'||G_AMW_GRANTS||' gra '
3448   ||'      ,'||G_AMW_USER||' u '
3449   ||'  where rcd.constraint_rev_id = :5 '
3450   ||'    and u.user_id = :6 '
3451   ||'    and u.user_name = gra.grantee_key '
3452   ||'    and gra.grantee_type = ''USER'' '
3453   ||'    and gra.menu_id = rcd.menu_id '
3454   ||'    and gra.instance_type = ''GLOBAL'' '
3455   ||'    and gra.object_id = -1 '
3456   ||'  UNION ALL '
3457   ||'  select rcd.function_id '
3458   ||'  from amw_role_constraint_denorm rcd '
3459   ||'      ,'||G_AMW_GRANTS||' gra '
3460   ||'  where rcd.constraint_rev_id = :7 '
3461   ||'    and gra.grantee_key = ''GLOBAL'' '
3462   ||'    and gra.grantee_type = ''GLOBAL'' '
3463   ||'    and gra.menu_id = rcd.menu_id '
3464   ||'    and gra.instance_type = ''GLOBAL'' '
3465   ||'    and gra.object_id = -1 '
3466   ||'  UNION ALL '
3467   ||'  select rcd.function_id '
3468   ||'  from amw_role_constraint_denorm rcd '
3469   ||'  where rcd.constraint_rev_id = :8 '
3470   ||'    and rcd.responsibility_id = :9 '
3471   ||') ';
3472 
3473 l_func_set_dynamic_sql   VARCHAR2(2500)  :=
3474     'select count(distinct group_code) from ( '
3475   ||'  select rcd.group_code '
3476   ||'  from amw_role_constraint_denorm rcd '
3477   ||'      ,'||G_AMW_USER_ROLES||' ur '
3478   ||'      ,'||G_AMW_user||' u '
3479   ||'  where rcd.constraint_rev_id = :1 '
3480   ||'    and u.user_id = :2 '
3481   ||'    and u.user_name = ur.user_name '
3482   ||'    and ur.role_name = rcd.role_name '
3483   ||'    and ur.role_orig_system = ''UMX'' '
3484   ||'  UNION ALL '
3485   ||'  select rcd.group_code '
3486   ||'  from amw_role_constraint_denorm rcd '
3487   ||'      ,'||G_AMW_USER_ROLES||' ur '
3488   ||'      ,'||G_AMW_user||' u '
3489   ||'  where rcd.constraint_rev_id = :3 '
3490   ||'    and u.user_id = :4 '
3491   ||'    and u.user_name = ur.user_name '
3492   ||'    and ur.role_orig_system_id = rcd.responsibility_id '
3493   ||'    and ur.role_orig_system = ''FND_RESP'' '
3494   ||'  UNION ALL '
3495   ||'  select rcd.group_code '
3496   ||'  from amw_role_constraint_denorm rcd '
3497   ||'      ,'||G_AMW_GRANTS||' gra '
3498   ||'      ,'||G_AMW_USER||' u '
3499   ||'  where rcd.constraint_rev_id = :5 '
3500   ||'    and u.user_id = :6 '
3501   ||'    and u.user_name = gra.grantee_key '
3502   ||'    and gra.grantee_type = ''USER'' '
3503   ||'    and gra.menu_id = rcd.menu_id '
3504   ||'    and gra.instance_type = ''GLOBAL'' '
3505   ||'    and gra.object_id = -1 '
3506   ||'  UNION ALL '
3507   ||'  select rcd.group_code '
3508   ||'  from amw_role_constraint_denorm rcd '
3509   ||'      ,'||G_AMW_GRANTS||' gra '
3510   ||'  where rcd.constraint_rev_id = :7 '
3511   ||'    and gra.grantee_key = ''GLOBAL'' '
3512   ||'    and gra.grantee_type = ''GLOBAL'' '
3513   ||'    and gra.menu_id = rcd.menu_id '
3514   ||'    and gra.instance_type = ''GLOBAL'' '
3515   ||'    and gra.object_id = -1 '
3516   ||'  UNION ALL '
3517   ||'  select rcd.group_code '
3518   ||'  from amw_role_constraint_denorm rcd '
3519   ||'  where rcd.constraint_rev_id = :8 '
3520   ||'    and rcd.responsibility_id = :9 '
3521   ||') ';
3522 
3523 -- get the name of the new respsonsibility which this user intends to have
3524 new_resp_c refCurTyp;
3525 l_new_resp_dynamic_sql   VARCHAR2(500)  :=
3526     'select resp.responsibility_name '
3527   ||'  from amw_role_constraint_denorm rcd '
3528   ||'      ,'||G_AMW_RESPONSIBILITY_VL||' resp '
3529   ||'  where rcd.constraint_rev_id = :1 and resp.responsibility_id = :2 '
3530   ||'    and rcd.responsibility_id = resp.responsibility_id ';
3531 
3532 -- get valid user waiver
3533 l_valid_user_waiver_count NUMBER;
3534 CURSOR c_valid_user_waivers (l_constraint_rev_id IN NUMBER, l_user_id IN NUMBER) IS
3535     SELECT count(*)
3536       FROM amw_constraint_waivers
3537      WHERE constraint_rev_id = l_constraint_rev_id
3538        AND object_type = 'USER'
3539        AND PK1 = l_user_id
3540        AND start_date <= sysdate AND (end_date >= sysdate or end_date is null);
3541 
3542 BEGIN
3543   -- default to 'N', which means user doesn't have violations
3544   has_violation := 'N';
3545   l_violat_existing_resp := NULL;
3546   l_violat_existing_role := NULL;
3547   l_violat_existing_menu := NULL;
3548   l_violat_new_resp := NULL;
3549   l_valid_user_waiver_count := 0;
3550 
3551   IF (p_user_id IS NOT NULL AND p_responsibility_id IS NOT NULL) THEN
3552     -- check all valid constraints
3553     OPEN c_all_valid_constraints;
3554     LOOP
3555      FETCH c_all_valid_constraints INTO l_all_valid_constraints;
3556      EXIT WHEN c_all_valid_constraints%NOTFOUND;
3557 
3558      -- check if this user is waived (due to User Waiver) from this constraint
3559      OPEN c_valid_user_waivers(l_all_valid_constraints.constraint_rev_id, p_user_id);
3560      FETCH c_valid_user_waivers INTO l_valid_user_waiver_count;
3561      CLOSE c_valid_user_waivers;
3562 
3563      -- 08.22.2005 tsho: consider only Prevent Constraint Objective
3564      -- IF l_valid_user_waiver_count <= 0 THEN
3565      IF l_valid_user_waiver_count <= 0 AND l_all_valid_constraints.objective_code = 'PR' THEN
3566 
3567       -- get the name of the new responsibility if combining this will results in violation against this constraint
3568       OPEN new_resp_c FOR l_new_resp_dynamic_sql USING
3569          l_all_valid_constraints.constraint_rev_id
3570         ,p_responsibility_id;
3571       FETCH new_resp_c INTO l_violat_new_resp;
3572       CLOSE new_resp_c;
3573 
3574       IF 'ALL' = l_all_valid_constraints.type_code THEN
3575         -- find the number of constraint entries(incompatible functions) by specified constraint_rev_id
3576         OPEN c_constraint_entries_count (l_all_valid_constraints.constraint_rev_id);
3577         FETCH c_constraint_entries_count INTO l_constraint_entries_count;
3578         CLOSE c_constraint_entries_count;
3579 
3580         -- find the number of distinct constraint entries this user can access
3581         OPEN func_acess_count_c FOR l_func_dynamic_sql USING
3582           l_all_valid_constraints.constraint_rev_id,
3583           p_user_id,
3584           l_all_valid_constraints.constraint_rev_id,
3585           p_user_id,
3586           l_all_valid_constraints.constraint_rev_id,
3587           p_user_id,
3588           l_all_valid_constraints.constraint_rev_id,
3589           l_all_valid_constraints.constraint_rev_id,
3590           p_responsibility_id;
3591         FETCH func_acess_count_c INTO l_func_access_count;
3592         CLOSE func_acess_count_c;
3593 
3594         -- in ALL type: if user can access to all entries of this constraint,
3595         -- he violates this constraint
3596         IF l_func_access_count = l_constraint_entries_count THEN
3597           -- once he violates at least one constraint, break the loop and inform FALSE to the caller
3598           FND_FILE.put_line(fnd_file.log, '------------ fail on constraint - ALL = '||l_all_valid_constraints.constraint_rev_id ||' ---------------');
3599           l_violat_existing_resp := Get_Violat_Existing_Resp_List (
3600                 p_user_id                   => p_user_id,
3601                 p_constraint_rev_id         => l_all_valid_constraints.constraint_rev_id,
3602                 p_constraint_type_code      => l_all_valid_constraints.type_code);
3603           l_violat_existing_role := Get_Violat_Existing_Role_List (
3604                 p_user_id                   => p_user_id,
3605                 p_constraint_rev_id         => l_all_valid_constraints.constraint_rev_id,
3606                 p_constraint_type_code      => l_all_valid_constraints.type_code);
3607           l_violat_existing_menu := Get_Violat_Existing_Menu_List (
3608                 p_user_id                   => p_user_id,
3609                 p_constraint_rev_id         => l_all_valid_constraints.constraint_rev_id,
3610                 p_constraint_type_code      => l_all_valid_constraints.type_code);
3611 
3612           -- concatinate return result(Violation Details)
3613           has_violation := l_violat_new_resp;
3614           IF l_violat_existing_resp IS NOT NULL THEN
3615             IF has_violation IS NOT NULL THEN
3616               has_violation := has_violation||', ';
3617             END IF;
3618             has_violation := has_violation||l_violat_existing_resp;
3619           END IF;
3620           IF l_violat_existing_role IS NOT NULL THEN
3621             IF has_violation IS NOT NULL THEN
3622               has_violation := has_violation||', ';
3623             END IF;
3624             has_violation := has_violation||l_violat_existing_role;
3625           END IF;
3626           IF l_violat_existing_menu IS NOT NULL THEN
3627             IF has_violation IS NOT NULL THEN
3628               has_violation := has_violation||', ';
3629             END IF;
3630             has_violation := has_violation||l_violat_existing_menu;
3631           END IF;
3632 
3633 		  fnd_message.set_name('AMW', 'AMW_SOD_VIOLATION');
3634 	      fnd_message.set_token('CONSTRAINT', l_all_valid_constraints.constraint_name);
3635 	      fnd_message.set_token('CONST_DETAILS', has_violation);
3636           return fnd_message.get;
3637         END IF;
3638 
3639       ELSIF 'ME' = l_all_valid_constraints.type_code THEN
3640         -- find the number of distinct constraint entries this user can access
3641         OPEN func_acess_count_c FOR l_func_dynamic_sql USING
3642           l_all_valid_constraints.constraint_rev_id,
3643           p_user_id,
3644           l_all_valid_constraints.constraint_rev_id,
3645           p_user_id,
3646           l_all_valid_constraints.constraint_rev_id,
3647           p_user_id,
3648           l_all_valid_constraints.constraint_rev_id,
3649           l_all_valid_constraints.constraint_rev_id,
3650           p_responsibility_id;
3651         FETCH func_acess_count_c INTO l_func_access_count;
3652         CLOSE func_acess_count_c;
3653 
3654         -- in ME type: if user can access at least two entries of this constraint,
3655         -- he violates this constraint
3656         IF l_func_access_count >= 2 THEN
3657           -- once he violates at least one constraint, break the loop and inform FALSE to the caller
3658           FND_FILE.put_line(fnd_file.log,'------------ fail on constraint - ME = '||l_all_valid_constraints.constraint_rev_id ||' ---------------');
3659           l_violat_existing_resp := Get_Violat_Existing_Resp_List (
3660                 p_user_id                   => p_user_id,
3661                 p_constraint_rev_id         => l_all_valid_constraints.constraint_rev_id,
3662                 p_constraint_type_code      => l_all_valid_constraints.type_code);
3663           l_violat_existing_role := Get_Violat_Existing_Role_List (
3664                 p_user_id                   => p_user_id,
3665                 p_constraint_rev_id         => l_all_valid_constraints.constraint_rev_id,
3666                 p_constraint_type_code      => l_all_valid_constraints.type_code);
3667           l_violat_existing_menu := Get_Violat_Existing_Menu_List (
3668                 p_user_id                   => p_user_id,
3669                 p_constraint_rev_id         => l_all_valid_constraints.constraint_rev_id,
3670                 p_constraint_type_code      => l_all_valid_constraints.type_code);
3671 
3672           -- concatinate return result(Violation Details)
3673           has_violation := l_violat_new_resp;
3674           IF l_violat_existing_resp IS NOT NULL THEN
3675             IF has_violation IS NOT NULL THEN
3676               has_violation := has_violation||', ';
3677             END IF;
3678             has_violation := has_violation||l_violat_existing_resp;
3679           END IF;
3680           IF l_violat_existing_role IS NOT NULL THEN
3681             IF has_violation IS NOT NULL THEN
3682               has_violation := has_violation||', ';
3683             END IF;
3684             has_violation := has_violation||l_violat_existing_role;
3685           END IF;
3686           IF l_violat_existing_menu IS NOT NULL THEN
3687             IF has_violation IS NOT NULL THEN
3688               has_violation := has_violation||', ';
3689             END IF;
3690             has_violation := has_violation||l_violat_existing_menu;
3691           END IF;
3692 
3693 		  fnd_message.set_name('AMW', 'AMW_SOD_VIOLATION');
3694 	      fnd_message.set_token('CONSTRAINT', l_all_valid_constraints.constraint_name);
3695 	      fnd_message.set_token('CONST_DETAILS', has_violation);
3696           return fnd_message.get;
3697         END IF;
3698 
3699       ELSIF 'SET' = l_all_valid_constraints.type_code THEN
3700         -- find the number of distinct constraint entries this user can access
3701         OPEN group_acess_count_c FOR l_func_set_dynamic_sql USING
3702           l_all_valid_constraints.constraint_rev_id,
3703           p_user_id,
3704           l_all_valid_constraints.constraint_rev_id,
3705           p_user_id,
3706           l_all_valid_constraints.constraint_rev_id,
3707           p_user_id,
3708           l_all_valid_constraints.constraint_rev_id,
3709           l_all_valid_constraints.constraint_rev_id,
3710           p_responsibility_id;
3711         FETCH group_acess_count_c INTO l_group_access_count;
3712         CLOSE group_acess_count_c;
3713 
3714         -- in SET type: if user can access at least two distinct groups(set) of this constraint,
3715         -- he violates this constraint
3716         IF l_group_access_count >= 2 THEN
3717           -- once he violates at least one constraint, break the loop and inform FALSE to the caller
3718           FND_FILE.put_line(fnd_file.log,'------------ fail on constraint - SET = '||l_all_valid_constraints.constraint_rev_id ||' ---------------');
3719           l_violat_existing_resp := Get_Violat_Existing_Resp_List (
3720                 p_user_id                   => p_user_id,
3721                 p_constraint_rev_id         => l_all_valid_constraints.constraint_rev_id,
3722                 p_constraint_type_code      => l_all_valid_constraints.type_code);
3723           l_violat_existing_role := Get_Violat_Existing_Role_List (
3724                 p_user_id                   => p_user_id,
3725                 p_constraint_rev_id         => l_all_valid_constraints.constraint_rev_id,
3726                 p_constraint_type_code      => l_all_valid_constraints.type_code);
3727           l_violat_existing_menu := Get_Violat_Existing_Menu_List (
3728                 p_user_id                   => p_user_id,
3729                 p_constraint_rev_id         => l_all_valid_constraints.constraint_rev_id,
3730                 p_constraint_type_code      => l_all_valid_constraints.type_code);
3731 
3732           -- concatinate return result(Violation Details)
3733           has_violation := l_violat_new_resp;
3734           IF l_violat_existing_resp IS NOT NULL THEN
3735             IF has_violation IS NOT NULL THEN
3736               has_violation := has_violation||', ';
3737             END IF;
3738             has_violation := has_violation||l_violat_existing_resp;
3739           END IF;
3740           IF l_violat_existing_role IS NOT NULL THEN
3741             IF has_violation IS NOT NULL THEN
3742               has_violation := has_violation||', ';
3743             END IF;
3744             has_violation := has_violation||l_violat_existing_role;
3745           END IF;
3746           IF l_violat_existing_menu IS NOT NULL THEN
3747             IF has_violation IS NOT NULL THEN
3748               has_violation := has_violation||', ';
3749             END IF;
3750             has_violation := has_violation||l_violat_existing_menu;
3751           END IF;
3752 
3753 		  fnd_message.set_name('AMW', 'AMW_SOD_VIOLATION');
3754 	      fnd_message.set_token('CONSTRAINT', l_all_valid_constraints.constraint_name);
3755 	      fnd_message.set_token('CONST_DETAILS', has_violation);
3756           return fnd_message.get;
3757         END IF;
3758       ELSE
3759         -- other constraint types
3760         NULL;
3761       END IF; -- end of if: constraint type_code
3762 
3763      END IF; --end of if: l_valid_user_waiver_count > 0
3764 
3765     END LOOP; --end of loop: c_all_valid_constraints
3766     CLOSE c_all_valid_constraints;
3767 
3768   END IF; -- end of if: p_user_id IS NOT NULL AND p_responsibility_id IS NOT NULL
3769 
3770   return has_violation;
3771 END;
3772 
3773 
3774 
3775 
3776 /*
3777  * cpetriuc
3778  * -------------
3779  * MENU_VIOLATES
3780  * -------------
3781  * Checks if the menu provided as argument violates any SOD (Segregation of Duties)
3782  * constraints.  If a constraint is violated, the function returns an error message
3783  * containing the name of the violated constraint together with the list of functions
3784  * that define the constraint.  Otherwise, the function returns 'N'.
3785  */
3786 function MENU_VIOLATES(p_menu_id NUMBER) return VARCHAR2 is
3787 
3788 g_constraint_function_id_list G_NUMBER_TABLE;
3789 g_constraint_group_code_list G_NUMBER_TABLE;
3790 g_group_code_list G_NUMBER_TABLE;
3791 g_menu_function_id_list G_NUMBER_TABLE;
3792 m_constraint_details VARCHAR2(3000);
3793 m_counter NUMBER;
3794 m_failed BOOLEAN;
3795 m_function_name VARCHAR2(240);
3796 m_return_text VARCHAR2(3000);
3797 
3798 
3799 cursor MENU_FUNCTIONS(p_menu_id NUMBER) is
3800 select distinct FUNCTION_ID
3801 from FND_COMPILED_MENU_FUNCTIONS
3802 where MENU_ID = p_menu_id;
3803 
3804 cursor CONSTRAINTS is
3805 select *
3806 from AMW_CONSTRAINTS_VL
3807 where
3808 (TYPE_CODE = 'ALL' or TYPE_CODE = 'ME' or TYPE_CODE = 'SET') and
3809 START_DATE <= sysdate and
3810 (END_DATE is null or END_DATE >= sysdate);
3811 
3812 cursor CONSTRAINT_ENTRIES(p_constraint_rev_id NUMBER) is
3813 select distinct FUNCTION_ID, GROUP_CODE
3814 from AMW_CONSTRAINT_ENTRIES
3815 where
3816 CONSTRAINT_REV_ID = p_constraint_rev_id and
3817 (OBJECT_TYPE = 'FUNC' or OBJECT_TYPE is null);
3818 
3819 cursor CONSTRAINT_GROUP_CODES(p_constraint_rev_id NUMBER) is
3820 select distinct GROUP_CODE
3821 from AMW_CONSTRAINT_ENTRIES
3822 where
3823 CONSTRAINT_REV_ID = p_constraint_rev_id and
3824 (OBJECT_TYPE = 'FUNC' or OBJECT_TYPE is null);
3825 
3826 
3827 begin
3828 
3829 open MENU_FUNCTIONS(p_menu_id);
3830 fetch MENU_FUNCTIONS bulk collect into g_menu_function_id_list;
3831 close MENU_FUNCTIONS;
3832 
3833 for constraint in CONSTRAINTS loop
3834 
3835 m_failed := FALSE;
3836 
3837 open CONSTRAINT_ENTRIES(constraint.CONSTRAINT_REV_ID);
3838 fetch CONSTRAINT_ENTRIES bulk collect into
3839 g_constraint_function_id_list,
3840 g_constraint_group_code_list;
3841 close CONSTRAINT_ENTRIES;
3842 
3843 for i in 1 .. g_constraint_function_id_list.COUNT loop
3844 
3845 select USER_FUNCTION_NAME into m_function_name
3846 from FND_FORM_FUNCTIONS_VL
3847 where FUNCTION_ID = g_constraint_function_id_list(i);
3848 
3849 if i = 1 then m_constraint_details := m_function_name;
3850 else m_constraint_details := m_constraint_details || ', ' || m_function_name;
3851 end if;
3852 
3853 end loop;
3854 
3855 ------------------------------------
3856 -- Process a constraint of type ALL.
3857 ------------------------------------
3858 if constraint.TYPE_CODE = 'ALL' then
3859 
3860 for i in 1 .. g_constraint_function_id_list.COUNT loop
3861 
3862 m_failed := FALSE;  -- Each constraint function must exist among the menu functions.
3863 
3864 for j in 1 .. g_menu_function_id_list.COUNT loop
3865 if g_constraint_function_id_list(i) = g_menu_function_id_list(j) then
3866 m_failed := TRUE;  -- This constraint function exists among the menu functions.
3867 exit;
3868 end if;
3869 end loop;
3870 
3871 if m_failed = FALSE then
3872 exit;  -- A constraint function has not been found among the menu functions.
3873 end if;
3874 
3875 end loop;
3876 
3877 end if;
3878 
3879 ------------------------------------------------------
3880 -- Process a constraint of type ME (Mutual Exclusion).
3881 ------------------------------------------------------
3882 if constraint.TYPE_CODE = 'ME' then
3883 
3884 m_counter := 0;
3885 for i in 1 .. g_constraint_function_id_list.COUNT loop
3886 for j in 1 .. g_menu_function_id_list.COUNT loop
3887 if g_constraint_function_id_list(i) = g_menu_function_id_list(j) then
3888 m_counter := m_counter + 1;
3889 end if;
3890 end loop;
3891 end loop;
3892 
3893 if m_counter >= 2 then m_failed := TRUE; end if;
3894 
3895 end if;
3896 
3897 ------------------------------------
3898 -- Process a constraint of type SET.
3899 ------------------------------------
3900 if constraint.TYPE_CODE = 'SET' then
3901 
3902 open CONSTRAINT_GROUP_CODES(constraint.CONSTRAINT_REV_ID);
3903 fetch CONSTRAINT_GROUP_CODES bulk collect into g_group_code_list;
3904 close CONSTRAINT_GROUP_CODES;
3905 
3906 m_failed := TRUE;  -- Assume the contrary.
3907 
3908 for i in 1 .. g_constraint_function_id_list.COUNT loop
3909 for j in 1 .. g_menu_function_id_list.COUNT loop
3910 if g_constraint_function_id_list(i) = g_menu_function_id_list(j) then
3911 g_group_code_list(g_constraint_group_code_list(i)) := 0;
3912 end if;
3913 end loop;
3914 end loop;
3915 
3916 for k in 1 .. g_group_code_list.COUNT loop
3917 if g_group_code_list(k) <> 0 then
3918 m_failed := FALSE;  -- Not all groups have at least one function among the menu functions.
3919 exit;
3920 end if;
3921 end loop;
3922 
3923 end if;
3924 
3925 -----------------------------------------------------------------------
3926 -- If this constraint has been violated, return an appropriate message.
3927 -----------------------------------------------------------------------
3928 if m_failed = TRUE then
3929 
3930 FND_MESSAGE.SET_NAME('AMW', 'AMW_SOD_VIOLATION');
3931 FND_MESSAGE.SET_TOKEN('CONSTRAINT', constraint.CONSTRAINT_NAME);
3932 FND_MESSAGE.SET_TOKEN('CONST_DETAILS', m_constraint_details);
3933 m_return_text := FND_MESSAGE.GET;
3934 
3935 return m_return_text;
3936 
3937 end if;
3938 
3939 end loop;  -- CONSTRAINTS cursor loop
3940 
3941 return 'N';
3942 
3943 
3944 end MENU_VIOLATES;
3945 
3946 
3947 
3948 
3949 /*
3950  * cpetriuc
3951  * ----------------------
3952  * FUNCTION_VIOLATES_MENU
3953  * ----------------------
3954  * Checks if any SOD (Segregation of Duties) constraints would be violated if the
3955  * argument function would be added to the menu provided as argument.  If a constraint
3956  * would be violated, the function returns an error message containing the name of the
3957  * potentially violated constraint together with the list of functions that define the
3958  * constraint.  Otherwise, the function returns 'N'.
3959  */
3960 function FUNCTION_VIOLATES_MENU(p_menu_id NUMBER, p_function_id NUMBER) return VARCHAR2 is
3961 
3962 g_constraint_function_id_list G_NUMBER_TABLE;
3963 g_constraint_group_code_list G_NUMBER_TABLE;
3964 g_group_code_list G_NUMBER_TABLE;
3965 g_menu_function_id_list G_NUMBER_TABLE;
3966 m_constraint_details VARCHAR2(3000);
3967 m_failed BOOLEAN;
3968 m_function_name VARCHAR2(240);
3969 m_return_text VARCHAR2(3000);
3970 
3971 
3972 cursor MENU_FUNCTIONS(p_menu_id NUMBER) is
3973 select distinct FUNCTION_ID
3974 from FND_COMPILED_MENU_FUNCTIONS
3975 where MENU_ID in
3976 (
3977 select MENU_ID
3978 from FND_MENU_ENTRIES
3979 start with MENU_ID = p_menu_id
3980 connect by prior MENU_ID = SUB_MENU_ID
3981 );
3982 
3983 cursor CONSTRAINTS is
3984 select *
3985 from AMW_CONSTRAINTS_VL
3986 where
3987 (TYPE_CODE = 'ALL' or TYPE_CODE = 'ME' or TYPE_CODE = 'SET') and
3988 START_DATE <= sysdate and
3989 (END_DATE is null or END_DATE >= sysdate);
3990 
3991 cursor CONSTRAINT_ENTRIES(p_constraint_rev_id NUMBER) is
3992 select distinct FUNCTION_ID, GROUP_CODE
3993 from AMW_CONSTRAINT_ENTRIES
3994 where
3995 CONSTRAINT_REV_ID = p_constraint_rev_id and
3996 (OBJECT_TYPE = 'FUNC' or OBJECT_TYPE is null);
3997 
3998 cursor CONSTRAINT_GROUP_CODES(p_constraint_rev_id NUMBER) is
3999 select distinct GROUP_CODE
4000 from AMW_CONSTRAINT_ENTRIES
4001 where
4002 CONSTRAINT_REV_ID = p_constraint_rev_id and
4003 (OBJECT_TYPE = 'FUNC' or OBJECT_TYPE is null);
4004 
4005 
4006 begin
4007 
4008 open MENU_FUNCTIONS(p_menu_id);
4009 fetch MENU_FUNCTIONS bulk collect into g_menu_function_id_list;
4010 close MENU_FUNCTIONS;
4011 
4012 for constraint in CONSTRAINTS loop
4013 
4014 m_failed := FALSE;
4015 
4016 open CONSTRAINT_ENTRIES(constraint.CONSTRAINT_REV_ID);
4017 fetch CONSTRAINT_ENTRIES bulk collect into
4018 g_constraint_function_id_list,
4019 g_constraint_group_code_list;
4020 close CONSTRAINT_ENTRIES;
4021 
4022 for i in 1 .. g_constraint_function_id_list.COUNT loop
4023 
4024 select USER_FUNCTION_NAME into m_function_name
4025 from FND_FORM_FUNCTIONS_VL
4026 where FUNCTION_ID = g_constraint_function_id_list(i);
4027 
4028 if i = 1 then m_constraint_details := m_function_name;
4029 else m_constraint_details := m_constraint_details || ', ' || m_function_name;
4030 end if;
4031 
4032 end loop;
4033 
4034 for i in 1 .. g_constraint_function_id_list.COUNT loop
4035 if g_constraint_function_id_list(i) = p_function_id then
4036 
4037 ------------------------------------
4038 -- Process a constraint of type ALL.
4039 ------------------------------------
4040 if constraint.TYPE_CODE = 'ALL' then
4041 for j in 1 .. g_constraint_function_id_list.COUNT loop
4042 
4043 m_failed := FALSE;  -- Each constraint function must exist among the menu functions.
4044 
4045 if i <> j then
4046 for k in 1 .. g_menu_function_id_list.COUNT loop
4047 if g_constraint_function_id_list(j) = g_menu_function_id_list(k) then
4048 m_failed := TRUE;  -- This constraint function exists among the menu functions.
4049 exit;
4050 end if;
4051 end loop;
4052 else m_failed := TRUE;  -- If i = j, continue the loop.
4053 end if;
4054 
4055 if m_failed = FALSE then
4056 exit;  -- A constraint function has not been found among the menu functions.
4057 end if;
4058 
4059 end loop;
4060 end if;
4061 
4062 ------------------------------------------------------
4063 -- Process a constraint of type ME (Mutual Exclusion).
4064 ------------------------------------------------------
4065 if constraint.TYPE_CODE = 'ME' then
4066 for j in 1 .. g_constraint_function_id_list.COUNT loop
4067 
4068 if i <> j then
4069 for k in 1 .. g_menu_function_id_list.COUNT loop
4070 if g_constraint_function_id_list(j) = g_menu_function_id_list(k) then
4071 m_failed := TRUE;
4072 exit;
4073 end if;
4074 end loop;
4075 end if;
4076 
4077 if m_failed = TRUE then
4078 exit;  -- At least one mutual exclusivity has been violated.
4079 end if;
4080 
4081 end loop;
4082 end if;
4083 
4084 ------------------------------------
4085 -- Process a constraint of type SET.
4086 ------------------------------------
4087 if constraint.TYPE_CODE = 'SET' then
4088 
4089 open CONSTRAINT_GROUP_CODES(constraint.CONSTRAINT_REV_ID);
4090 fetch CONSTRAINT_GROUP_CODES bulk collect into g_group_code_list;
4091 close CONSTRAINT_GROUP_CODES;
4092 
4093 g_group_code_list(g_constraint_group_code_list(i)) := 0;
4094 
4095 m_failed := TRUE;  -- Assume the contrary.
4096 
4097 for j in 1 .. g_constraint_function_id_list.COUNT loop
4098 if i <> j then
4099 for k in 1 .. g_menu_function_id_list.COUNT loop
4100 if g_constraint_function_id_list(j) = g_menu_function_id_list(k) then
4101 g_group_code_list(g_constraint_group_code_list(j)) := 0;
4102 end if;
4103 end loop;
4104 end if;
4105 end loop;
4106 
4107 for l in 1 .. g_group_code_list.COUNT loop
4108 if g_group_code_list(l) <> 0 then
4109 m_failed := FALSE;  -- Not all groups have at least one function among the menu functions.
4110 exit;
4111 end if;
4112 end loop;
4113 
4114 end if;
4115 
4116 -----------------------------------------------------------------------
4117 -- If this constraint has been violated, return an appropriate message.
4118 -----------------------------------------------------------------------
4119 if m_failed = TRUE then
4120 
4121 FND_MESSAGE.SET_NAME('AMW', 'AMW_SOD_VIOLATION');
4122 FND_MESSAGE.SET_TOKEN('CONSTRAINT', constraint.CONSTRAINT_NAME);
4123 FND_MESSAGE.SET_TOKEN('CONST_DETAILS', m_constraint_details);
4124 m_return_text := FND_MESSAGE.GET;
4125 
4126 return m_return_text;
4127 
4128 end if;
4129 
4130 end if;  -- if g_constraint_function_id_list(i) = p_function_id
4131 end loop;  -- g_constraint_function_id_list loop
4132 
4133 end loop;  -- CONSTRAINTS cursor loop
4134 
4135 return 'N';
4136 
4137 
4138 end FUNCTION_VIOLATES_MENU;
4139 
4140 -- ----------------------------------------------------------------------
4141 END AMW_VIOLATION_PVT;