DBA Data[Home] [Help]

PACKAGE BODY: APPS.FND_USER_PKG

Source


1 package body FND_USER_PKG as
2 /* $Header: AFSCUSRB.pls 120.63.12020000.3 2012/10/11 02:40:37 ctilley ship $ */
3 
4 /* START PARTY */
5 C_PKG_NAME      CONSTANT VARCHAR2(30) := 'FND_USER_PKG';
6 C_LOG_HEAD      CONSTANT VARCHAR2(30) := 'fnd.plsql.FND_USER_PKG.';
7 
8 /* One level cache for derive_person_party_id */
9 Z_EMPLOYEE_ID NUMBER := NULL;
10 Z_CUSTOMER_ID NUMBER := NULL;
11 Z_PERSON_PARTY_ID NUMBER := NULL;
12 
13 /* One level cache for derive_customer_and_or_emp */
14 Z_REV_EMPLOYEE_ID NUMBER := NULL;
15 Z_REV_CUSTOMER_ID NUMBER := NULL;
16 Z_REV_PERSON_PARTY_ID NUMBER := NULL;
17 /* END PARTY */
18 
19 /* bug 2504562 */
20 g_old_user_name varchar2(100) := NULL;
21 
22 /* bug 4318754, 4352995 SSO related changes */
23 g_old_user_guid RAW(16) := NULL;
24 g_old_person_party_id NUMBER := NULL;
25 
26 -- bug 8227171
27 g_event_controller varchar2(10);
28 
29 /* bug 13472484  - FND_USER_PKG.UpdateUserInternal sets this var to be used from the following flow
30  * UpdateUserInternal -> fnd_web_sec.change_password ->
31  * fnd_user_pkg.ldap_wrapper_update_user.  This var is to indicate whether to pass expiry flag to ldap wrapper
32  * when called from fnd_web_sec.change_password APIs since this calculation is
33  * done in UpdateUserInternal already.
34  */
35 G_EXPIRE_USER_PWD    pls_integer := NULL;
36 
37 
38 ----------------------------------------------------------------------------
39 --
40 -- boolRet (INTERNAL)
41 --   Translate Y/N to boolean
42 --
43 function boolRet(ret varchar2) return boolean is
44 begin
45   if (ret = 'Y') then
46     return TRUE;
47   end if;
48   return FALSE;
49 end;
50 
51 ---------------------------------------------------------------------------
52 -- ldap_wrapper_create_user (INTERNAL)
53 --
54 procedure ldap_wrapper_create_user(x_user_name in varchar2,
55                                    x_unencrypted_password in varchar2,
56                                    x_start_date in date,
57                                    x_end_date in date,
58                                    x_description in varchar2,
59                                    x_email_address in varchar2,
60                                    x_fax in varchar2,
61                                    x_expire_pwd in pls_integer,
62                                    x_user_guid in out nocopy raw,
63                                    x_oid_pwd in out nocopy varchar2) is
64 l_result pls_integer;
65 reason varchar2(2000);
66 l_pwd varchar2(100);
67 pwdCaseOpt varchar2(1);
68 begin
69 
70   l_result := null;
71 
72   -- Bug 5161497
73   l_pwd := x_unencrypted_password;
74   pwdCaseOpt := null;
75   -- Bug 5162136 Note: Creating user so use SITE level profile value.
76   -- Bug 8664441 - pass in initial values for the security context to ensure the site value is used.
77   pwdCaseOpt := fnd_profile.value_specific(name =>'SIGNON_PASSWORD_CASE',
78                                            user_id => -1,
79                                            responsibility_id => -1,
80                                            application_id => -1,
81                                            org_id => -1,
82                                            server_id => -1);
83 
84   if (pwdCaseOpt is null) or (pwdCaseOpt = '1') then
85     l_pwd := lower(x_unencrypted_password);
86   end if;
87 
88   -- Bug: 5375111
89   -- Calling ldap_wrapper_wrapper with the new expire_pwd flag.
90   fnd_ldap_wrapper.create_user(x_user_name, l_pwd, x_start_date, x_end_date,
91      x_description, x_email_address, x_fax, x_expire_pwd, x_user_guid,
92      x_oid_pwd, l_result);
93 
94   if (l_result <> fnd_ldap_wrapper.G_SUCCESS) then
95     reason := fnd_message.get;
96     fnd_message.set_name('FND', 'LDAP_WRAPPER_CREATE_USER_FAIL');
97     fnd_message.set_token('USER_NAME', x_user_name);
98     fnd_message.set_token('REASON', reason);
99     app_exception.raise_exception;
100   end if;
101 
102 exception
103   when others then
104     fnd_message.set_name('FND', 'LDAP_WRAPPER_CREATE_USER_FAIL');
105     fnd_message.set_token('USER_NAME', x_user_name);
106     fnd_message.set_token('REASON', sqlerrm);
107     app_exception.raise_exception;
108 end;
109 
110 ----------------------------------------------------------------------^M
111 --
112 -- UpdateUserInternal (PRIVATE)
113 --   Internal api for UpdateUser and UpdateUserParty.
114 --   Not exposed publicly, use UpdateUser or UpdateUserParty wrappers.
115 --
116 procedure UpdateUserInternal (
117   x_user_name                  in varchar2,
118   x_owner                      in varchar2,
119   x_unencrypted_password       in varchar2,
120   x_session_number             in number,
121   x_start_date                 in date,
122   x_end_date                   in date,
123   x_last_logon_date            in date,
124   x_description                in varchar2,
125   x_password_date              in date,
126   x_password_accesses_left     in number,
127   x_password_lifespan_accesses in number,
128   x_password_lifespan_days     in number,
129   x_employee_id                in number,
130   x_email_address              in varchar2,
131   x_fax                        in varchar2,
132   x_customer_id                in number,
133   x_supplier_id                in number,
134   x_person_party_id            in number,
135   x_old_password               in varchar2,
136   x_mode                       in varchar2,
137   x_last_update_date           in date default sysdate,
138   x_user_guid                  in raw default null,
139   x_change_source              in number default null)
140 is
141   l_api_name varchar2(30) := 'UPDATEUSERINTERNAL';
142   owner_id  number := 0;
143   ret       varchar2(1);
144   reason    varchar2(32000);
145   l_session_number number;
146   l_start_date date;
147   l_end_date date;
148   l_last_logon_date date;
149   l_description varchar2(240);
150   l_password_date date;
151   l_password_accesses_left number;
152   l_password_lifespan_accesses number;
153   l_password_lifespan_days number;
154   l_employee_id number;
155   l_email_address varchar2(240);
156   l_fax varchar2(80);
157   l_customer_id number;
158   l_supplier_id number;
159   l_person_party_id number;
160   -- Added for Function Security Cache Invalidation
161   l_user_id number;
162   l_user_guid raw(16);
163 
164   -- This cursor was added to fix Bug#3663908
165   l_old_customer_id number;
166   l_old_employee_id number;
167   l_old_person_party_id number;
168   l_old_user_guid RAW(16);
169   l_old_supplier_id number; -- bug 10371150
170 
171   l_parameter_list wf_parameter_list_t;  -- bug 8227171 WF event parameter list
172 
173   -- bug 10371150 Add supplier_id
174   cursor usercur is
175   select customer_id, employee_id, person_party_id, user_guid, supplier_id
176   from fnd_user
177   where user_name = upper(x_user_name);
178 
179   -- Bug 5235329
180   l_expire_pwd pls_integer;
181 
182   l_icx_sec_attr_exists number;
183   l_person_sec_attr_exists number;
184 
185   -- Bug 14673409 needed store the new/derived customer, employee and/or person_party_id
186   new_customer_id number;
187   new_employee_id number;
188   new_person_party_id number;
189 
190 begin
191   if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
192        fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
193                      'Begin');
194   end if;
195 
196   -- Bug 7687370
197   if (x_owner is null) then
198     owner_id := fnd_global.user_id;
199   else
200     owner_id := fnd_load_util.owner_id(x_owner);
201   end if;
202 
203   -- This was added to fix Bug#3663908
204   open usercur;
205   fetch usercur into l_old_customer_id, l_old_employee_id,
206                      l_old_person_party_id, l_old_user_guid,
207                      l_old_supplier_id; -- bug 10371150
208   close usercur;
209 
210   -- bug 4318754 for SSO stuff
211   g_old_person_party_id := l_old_person_party_id;
212   g_old_user_guid := l_old_user_guid;
213   -- end bug 4318754
214 
215   if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
216       fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
217                      'Retrieved originating values: person_party_id = '||l_old_person_party_id||',customer_id='||l_old_customer_id||
218                       ',employee_id='||l_old_employee_id||' and supplier_id='||l_old_supplier_id);
219   end if;
220 
221   -- Bug4680643 get values for start_date and end_date from the database.
222   -- Bug 7311525 get the user_id now so we can use it for identifying GUEST
223   select start_date, end_date, user_id
224      into l_start_date, l_end_date, l_user_id
225      from fnd_user
226   where user_name = upper(x_user_name);
227 
228   -- Bug4680643 Determine and set the value of start_date and end_date
229   -- outside of the decode statement which was truncating the actual
230   -- value when it is already set.
231 
232   if (x_start_date = fnd_user_pkg.null_date) then
233     -- For this if condition error exception needs to be raised as
234     -- start date cannot be null. This will be resolved through a new bug.
235     l_start_date := null;
236   elsif (x_start_date is not null) then
237       -- bug 9054462 make sure we do not permit GUEST start_date to be
238       -- post-dated which would cause the GUEST user account to expire.
239       -- If start_date > sysdate, do not update the start_date for GUEST.
240       if (l_user_id = 6) then
241          if (x_start_date > sysdate) then
242             -- throw the error message SECURITY-GUEST START DATE
243             fnd_message.set_name('FND', 'SECURITY-GUEST START DATE');
244             app_exception.raise_exception;
245          else
246             l_start_date := x_start_date;
247          end if;
248       else
249          l_start_date := x_start_date;
250       end if;
251   end if;
252 
253   -- Bug 4901996. Truncate the time stamp
254   l_start_date := trunc(l_start_date);
255 
256   if (x_end_date = fnd_user_pkg.null_date) then
257       l_end_date := null;
258   elsif (x_end_date is not null) then
259     -- Bug 7311525 make sure we do not permit GUEST to be end-dated
260     if (l_user_id <> 6) then
261       l_end_date := x_end_date;
262     else  -- unenddate GUEST
263       l_end_date := null;
264     end if;
265   end if;
266   -- Bug 4901996. Truncate the time stamp
267   l_end_date := trunc(l_end_date);
268 
269   -- Translate *NULL* parameter values into real nulls,
270   -- treat null values as no-change.
271   begin
272     select decode(x_session_number, fnd_user_pkg.null_number, null,
273                   null, u.session_number,
274                   x_session_number),
275            -- bug 6608790 this preserves timestamp for iRecruitement
276            decode(x_last_logon_date, fnd_user_pkg.null_date, to_date(null),
277                   to_date(null), u.last_logon_date,
278                   x_last_logon_date),
279            decode(x_description, fnd_user_pkg.null_char, null,
280                   null, u.description,
281                   x_description),
282            decode(x_password_date, fnd_user_pkg.null_date, null,
283                   null, u.password_date,
284                   x_password_date),
285            decode(x_password_accesses_left, fnd_user_pkg.null_number, null,
286                   null, u.password_accesses_left,
287                   x_password_accesses_left),
288            decode(x_password_lifespan_accesses, fnd_user_pkg.null_number, null,
289                   null, u.password_lifespan_accesses,
290                   x_password_lifespan_accesses),
291            decode(x_password_lifespan_days, fnd_user_pkg.null_number, null,
292                   null, u.password_lifespan_days,
293                   x_password_lifespan_days),
294            decode(x_employee_id, fnd_user_pkg.null_number, null,
295                   null, u.employee_id,
296                   x_employee_id),
297            decode(x_email_address, fnd_user_pkg.null_char, null,
298                   null, u.email_address,
299                   x_email_address),
300            decode(x_fax, fnd_user_pkg.null_char, null,
301                   null, u.fax,
302                   x_fax),
303            decode(x_customer_id, fnd_user_pkg.null_number, null,
304                   null, u.customer_id,
305                   x_customer_id),
306            decode(x_supplier_id, fnd_user_pkg.null_number, null,
307                   null, u.supplier_id,
308                   x_supplier_id),
309            decode(x_person_party_id, fnd_user_pkg.null_number, null,
310                   null, u.person_party_id,
311                   x_person_party_id),
312            decode(x_user_guid, fnd_user_pkg.null_raw, null,
313                   null, u.user_guid,
314                   x_user_guid )
315     into l_session_number,
316          l_last_logon_date, l_description, l_password_date,
317          l_password_accesses_left, l_password_lifespan_accesses,
318          l_password_lifespan_days, l_employee_id,
319          l_email_address, l_fax, l_customer_id, l_supplier_id,
320          l_person_party_id , l_user_guid
321     from fnd_user u
322     where u.user_name = upper(x_user_name);
323   exception
324     when others then
325       fnd_message.set_name('FND', 'FND_INVALID_USER');
326       fnd_message.set_token('USER_NAME', X_USER_NAME);
327       app_exception.raise_exception;
328   end;
329 
330   -- PARTY
331   if (x_mode = 'PARTY') then
332     -- Called from UpdateUserParty
333     -- Derive customer/employee_ids from party_id
334     -- This was added to fix Bug#3663908
335     if (nvl(l_old_person_party_id, 0) <> nvl(l_person_party_id, 0)) then
336 
337       fnd_user_pkg.derive_customer_employee_id(x_user_name, l_person_party_id, l_customer_id, l_employee_id);
338 
339       if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
340             fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,'Derive employee_id = '||l_employee_id||
341                           ' derived customer_id = '||l_customer_id);
342       end if;
343     end if;
344   else
345     -- Called from UpdateUser
346     -- Derive the party_id from the customer/employee_ids.
347     -- This was added to fix Bug#3663908
348      if (nvl(l_old_customer_id, 0) <> nvl(l_customer_id, 0)) or (nvl(l_old_employee_id, 0) <> nvl(l_employee_id, 0)) then
349 
350         l_person_party_id := fnd_user_pkg.derive_person_party_id(x_user_name, l_customer_id, l_employee_id);
351 
352         if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
353             fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,'Derive party id = '||l_person_party_id);
354         end if;
355 
356 
357      end if;
358   end if;
359 
360 
361 
362 SAVEPOINT update_user;
363 
364   if (x_unencrypted_password is not null) then
365 
366      /* Bug 13472484 - calculate and set global to indicate pwd should
367       * be expired when updating OID pwd.  Not necessary if EXTERNAL.
368       * Setting a global so that it can be checked in fnd_web_sec APIs
369       * rather than updating all the signatures for pwd mgmt*/
370 
371        if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
372           fnd_log.string(FND_LOG.LEVEL_STATEMENT,
373                      c_log_head || l_api_name || '.pwdExpire',
374                      'Password is not null so set global if not external');
375        end if;
376 
377 
378        if (x_unencrypted_password <> FND_WEB_SEC.EXTERNAL_PWD) then
379 
380           -- Bug 13707735 - removed the condition that was added for bug13595376
381           -- this condition is incorrect - removed from both create and update flows.
382           -- NOTE:  This condition should be the same as used in FND_SIGNON.IS_PWD_EXPIRED
383 
384           if (l_password_date is null or
385                (l_password_lifespan_accesses is not null and
386                  nvl(l_password_accesses_left, 0) < 1) or
387                 (l_password_lifespan_days is not null and
388                  sysdate >= l_password_date + l_password_lifespan_days)) then
389 
390 
391                  if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
392                      fnd_log.string(FND_LOG.LEVEL_STATEMENT,
393                      c_log_head || l_api_name || '.pwdExpire',
394                      'pwd is not external and should be EXPIRED');
395                  end if;
396 
397                  G_EXPIRE_USER_PWD := fnd_ldap_wrapper.G_TRUE;
398             else
399                  if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
400                      fnd_log.string(FND_LOG.LEVEL_STATEMENT,
401                      c_log_head || l_api_name || '.pwdExpire',
402                      'pwd is not external and should NOT be EXPIRED');
403                  end if;
404 
405                  G_EXPIRE_USER_PWD := fnd_ldap_wrapper.G_FALSE;
406             end if; -- End calculating pwd expiration - bug 13472484
407 
408         end if; -- End calculating password expiration for non-EXTERNAL pwds
409 
410        if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
411                      fnd_log.string(FND_LOG.LEVEL_STATEMENT,
412                      c_log_head || l_api_name || '.before_updusr',
413                      'Now change password');
414        end if;
415 
416 
417      -- If old_password is provided, change the password of an
418      -- applications user after verifying the existing password.  This
419      -- change is being added for bug 2658982 and 1722166.
420      if (x_old_password is not null) then
421         -- Add fifth argument to not use autonomous transaction when chaning
422         -- passowrd. This is for bug 5087728
423         ret := fnd_web_sec.change_password(x_user_name,
424                                            x_old_password,
425                                            x_unencrypted_password,
426                                            x_unencrypted_password,
427                                            FALSE);
428      -- Otherwise, change the password of an applications user without
429      -- verifying the existing password
430      else
431         -- Add third argument to not use autonomous transaction when chaning
432         -- passowrd. This is for bug 5087728
433         ret := fnd_web_sec.change_password(x_user_name,
434                                            x_unencrypted_password, FALSE);
435         -- Bug 5355566/5840007 reset unsuccessful logins start date since
436         -- password is new and login with this password has not yet occurred.
437         if (x_last_logon_date is null) then
438           l_last_logon_date := sysdate;
439         end if;
440 
441      end if;
442 
443      -- Bug 13472484
444      -- Resetting variable to NULL now that the change_password call is complete.
445      -- Any further calls to ldap_wrapper_update_user will use the arg
446      -- passed or its default
447         if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
448             fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
449                   'Set G_EXPIRE_USER_PWD to null');
450         end if;
451         G_EXPIRE_USER_PWD := NULL;
452 
453     if (ret = 'N') then
454       reason := fnd_message.get();
455       fnd_message.set_name('FND', 'FND_CHANGE_PASSWORD_FAILED');
456       fnd_message.set_token('USER_NAME', X_USER_NAME);
457       fnd_message.set_token('REASON', reason);
458       app_exception.raise_exception;
459     end if;
460   end if;
461 
462   -- Bug 8227171 UpdateUserInternal
463   -- Raise WF event oracle.apps.fnd.pre.email.update
464   begin
465     wf_event.AddParameterToList('NEW_EMAIL', l_email_address, l_parameter_list);
466     wf_event.raise3(p_event_name =>'oracle.apps.fnd.pre.email.update',
467                   p_event_key => l_user_id,
468                   p_event_data => NULL,
469                   p_parameter_list => l_parameter_list,
470                   p_send_date => Sysdate);
471     exception
472          when others then
473           reason := fnd_message.get_encoded;
474           if (reason is not null) then
475             fnd_message.set_encoded(reason);
476           else
477             fnd_message.set_name('FND', 'FND_CREATE_A_SYNCH_MSG');
478           end if;
479           app_exception.raise_exception;
480   end;
481 
482   if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
483   fnd_log.string(FND_LOG.LEVEL_STATEMENT,
484                      c_log_head || l_api_name || '.before_upduser',
485                      'UpdateUser(): before updating user');
486   end if;
487 
488    if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
489             fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
490                      'Updating user with l_person_party_id = '||l_person_party_id||
491                      ', l_employee_id = '||l_employee_id||
492                      ', l_customer_id = '||l_customer_id||
493                      'and l_supplier_id = '||l_supplier_id);
494    end if;
495 
496   -- Update all of the non-password columns
497   update fnd_user set
498     last_update_date = x_last_update_date,
499     last_updated_by = owner_id,
500     last_update_login = owner_id,
501     session_number =  l_session_number,
502     start_date = l_start_date,
503     end_date = l_end_date,
504     last_logon_date = l_last_logon_date,
505     description = l_description,
506     password_date = l_password_date,
507     password_accesses_left = l_password_accesses_left,
508     password_lifespan_accesses = l_password_lifespan_accesses,
509     password_lifespan_days = l_password_lifespan_days,
510     employee_id = l_employee_id,
511     email_address = l_email_address,
512     fax = l_fax,
513     customer_id = l_customer_id,
514     supplier_id = l_supplier_id,
515     person_party_id = l_person_party_id,
516     user_guid = l_user_guid
517   where user_name = upper(x_user_name);
518 
519   if (SQL%NOTFOUND) then
520     fnd_message.set_name('FND', 'FND_INVALID_USER');
521     fnd_message.set_token('USER_NAME', X_USER_NAME);
522     app_exception.raise_exception;
523   else
524     -- bug 8227171 relocated the user_id fetch higher up.
525     -- Added for Function Security Cache Invalidation
526     fnd_function_security_cache.update_user(l_user_id);
527   end if;
528 
529 
530   if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
531   fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
532                      'Start calling ldap_wrapper_update_user');
533   fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
534                    'x_user_name = '||x_user_name);
535   end if;
536 
537   -- Enhancement 5027812
538   if (x_change_source is null or
539       x_change_source <> fnd_user_pkg.change_source_oid ) then
540     begin
541 
542       -- Bug 13472484 - removed the passing of the password since the password
543       -- will be changed higher up in the call to fnd_web_sec.change_password.
544       -- This second attempt to change the password will result in an error if
545       -- password history is enabled.
546       -- G_EXPIRE_USER_PWD is NULL - this call will use the default of 0.
547      if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
548          fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
549                      'G_EXPIRE_USER_PWD is null and now expect the default of 0 to be used');
550      end if;
551 
552       ldap_wrapper_update_user(x_user_name => upper(x_user_name),
553                                x_unencrypted_password => null,
554                                x_start_date => x_start_date,
555                                x_end_date => x_end_date,
556                                x_description => x_description,
557                                x_email_address => x_email_address,
558                                x_fax => x_fax);
559     exception
560     when others then
561       ROLLBACK to update_user;
562       reason := fnd_message.get();
563       fnd_message.set_name('FND', 'FND_USER_UPDATE_FAILED');
564       fnd_message.set_token('USERNAME', X_USER_NAME);
565       fnd_message.set_token('USERID', l_user_id);
566       fnd_message.set_token('REASON', reason);
567       app_exception.raise_exception;
568     end;
569   end if;
570   -- End bug 4318754, 4424225
571 
572   if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
573   fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
574                      'After calling ldap_wrapper_update_user');
575   end if;
576 
577   -- Enhancement 7311235 / Bug 8222658
578   -- Just like the FND Define User form, add/modify default securing
579   -- attributes to AK_WEB_USER_SEC_ATTR_VALUES as the final step
580   -- in the process of creating or updating a user.
581   -- Determine which attributes apply based on employee_id,
582   -- customer_id, supplier_id.
583   -- Bug 13989225
584   if (l_employee_id is not null) then
585     begin
586        -- Determine if the ICX Attributes exist already for this user regardless
587        -- of the employee_id associated
588        select count(1) into l_icx_sec_attr_exists from AK_WEB_USER_SEC_ATTR_VALUES
589        where  WEB_USER_ID = l_user_id
590        and ATTRIBUTE_CODE = 'ICX_HR_PERSON_ID'
591        and ATTRIBUTE_APPLICATION_ID = 178;
592 
593        select count(1) into l_person_sec_attr_exists from AK_WEB_USER_SEC_ATTR_VALUES
594        where  WEB_USER_ID = l_user_id
595        and ATTRIBUTE_CODE = 'TO_PERSON_ID'
596        and ATTRIBUTE_APPLICATION_ID = 178;
597 
598      if (l_old_employee_id is null) then
599         -- Attribute should not be there so insert the records
600         insert into AK_WEB_USER_SEC_ATTR_VALUES (
601           WEB_USER_ID,
602           ATTRIBUTE_CODE,
603           ATTRIBUTE_APPLICATION_ID,
604           NUMBER_VALUE,
605           CREATED_BY,
606           CREATION_DATE,
607           LAST_UPDATED_BY,
608           LAST_UPDATE_DATE,
609           LAST_UPDATE_LOGIN)
610         values (
611           l_user_id,
612           'ICX_HR_PERSON_ID',
613           178,
614           l_employee_id,
615           owner_id,
616           sysdate,
617           owner_id,
618           sysdate,
619           owner_id);
620 
621        insert into AK_WEB_USER_SEC_ATTR_VALUES (
622           WEB_USER_ID,
623           ATTRIBUTE_CODE,
624           ATTRIBUTE_APPLICATION_ID,
625           NUMBER_VALUE,
626           CREATED_BY,
627           CREATION_DATE,
628           LAST_UPDATED_BY,
629           LAST_UPDATE_DATE,
630           LAST_UPDATE_LOGIN)
631         values (
632           l_user_id,
633           'TO_PERSON_ID',
634           178,
635           l_employee_id,
636           owner_id,
637           sysdate,
638           owner_id,
639           sysdate,
640           owner_id);
641 
642      elsif (l_employee_id <> l_old_employee_id) then
643 
644        -- If the attribute exists then update...otherwise insert new records
645         if (l_icx_sec_attr_exists = 0) then
646             insert into AK_WEB_USER_SEC_ATTR_VALUES (
647                WEB_USER_ID,
648                ATTRIBUTE_CODE,
649                ATTRIBUTE_APPLICATION_ID,
650                NUMBER_VALUE,
651                CREATED_BY,
652                CREATION_DATE,
653                LAST_UPDATED_BY,
654                LAST_UPDATE_DATE,
655                LAST_UPDATE_LOGIN)
656             values (
657                l_user_id,
658                'ICX_HR_PERSON_ID',
659                178,
660                l_employee_id,
661                owner_id,
662                sysdate,
663                owner_id,
664                sysdate,
665                owner_id);
666         else
667 
668          -- Update existing record - ICX_HR_PERSON_ID
669           update AK_WEB_USER_SEC_ATTR_VALUES set
670               NUMBER_VALUE = l_employee_id,
671               LAST_UPDATED_BY = owner_id,
672               LAST_UPDATE_DATE = sysdate,
673               LAST_UPDATE_LOGIN = owner_id
674           where WEB_USER_ID = l_user_id
675           and ATTRIBUTE_CODE = 'ICX_HR_PERSON_ID'
676           and ATTRIBUTE_APPLICATION_ID = 178
677           and NUMBER_VALUE = l_old_employee_id; -- Bug 10371150
678 
679         end if;
680 
681         if (l_person_sec_attr_exists = 0) then
682             insert into AK_WEB_USER_SEC_ATTR_VALUES (
683                WEB_USER_ID,
684                ATTRIBUTE_CODE,
685                ATTRIBUTE_APPLICATION_ID,
686                NUMBER_VALUE,
687                CREATED_BY,
688                CREATION_DATE,
689                LAST_UPDATED_BY,
690                LAST_UPDATE_DATE,
691                LAST_UPDATE_LOGIN)
692             values (
693                l_user_id,
694                'TO_PERSON_ID',
695                178,
696                l_employee_id,
697                owner_id,
698                sysdate,
699                owner_id,
700                sysdate,
701                owner_id);
702         else
703           -- Update existing record - TO__PERSON_ID
704           update AK_WEB_USER_SEC_ATTR_VALUES set
705               NUMBER_VALUE = l_employee_id,
706               LAST_UPDATED_BY = owner_id,
707               LAST_UPDATE_DATE = sysdate,
708               LAST_UPDATE_LOGIN = owner_id
709           where WEB_USER_ID = l_user_id
710           and ATTRIBUTE_CODE = 'TO_PERSON_ID'
711           and ATTRIBUTE_APPLICATION_ID = 178
712           and NUMBER_VALUE = l_old_employee_id; -- Bug 10371150
713         end if;
714     end if;
715       exception
716           when others then
717            fnd_message.set_name( 'FND','SQL_PLSQL_ERROR' );
718            fnd_message.set_token('ROUTINE', l_api_name);
719    	    fnd_message.set_token('ERRNO', SQLCODE);
720  	    fnd_message.set_token('REASON', SQLERRM);
721     end;
722   else -- l_employee_id is NULL
723 
724      -- Bug 13989225 if new employee_id is null then delete
725      -- this doesn't work if the securing attributes have been changed
726      -- manually to other employees.  Those securing attributs will still remain.
727 
728     if (l_employee_id is null and l_old_employee_id is not null) then
729       begin
730         -- Delete securing attrs if new value is null
731         delete from AK_WEB_USER_SEC_ATTR_VALUES
732         where ATTRIBUTE_CODE = 'ICX_HR_PERSON_ID'
733         and ATTRIBUTE_APPLICATION_ID = 178
734         and WEB_USER_ID = l_user_id
735         and NUMBER_VALUE = l_old_employee_id;
736 
737         delete from AK_WEB_USER_SEC_ATTR_VALUES
738         where ATTRIBUTE_CODE = 'TO_PERSON_ID'
739         and ATTRIBUTE_APPLICATION_ID = 178
740         and WEB_USER_ID = l_user_id
741         and NUMBER_VALUE = l_old_employee_id;
742 
743         exception
744           when others then
745            fnd_message.set_name( 'FND','SQL_PLSQL_ERROR' );
746            fnd_message.set_token('ROUTINE', l_api_name);
747 	   fnd_message.set_token('ERRNO', SQLCODE);
748  	   fnd_message.set_token('REASON', SQLERRM);
749       end;
750     end if;
751   end if;
752 
753   if (l_customer_id is not null) then
754     begin
755       update AK_WEB_USER_SEC_ATTR_VALUES set
756         NUMBER_VALUE = l_customer_id,
757         LAST_UPDATED_BY = owner_id,
758         LAST_UPDATE_DATE = sysdate,
759         LAST_UPDATE_LOGIN = owner_id
760       where WEB_USER_ID = l_user_id
761       and ATTRIBUTE_CODE = 'ICX_CUSTOMER_CONTACT_ID'
762       and ATTRIBUTE_APPLICATION_ID = 178
763       and NUMBER_VALUE = l_old_customer_id; -- bug 10371150
764 
765       if (sql%rowcount = 0) then
766         insert into AK_WEB_USER_SEC_ATTR_VALUES (
767           WEB_USER_ID,
768           ATTRIBUTE_CODE,
769           ATTRIBUTE_APPLICATION_ID,
770           NUMBER_VALUE,
771           CREATED_BY,
772           CREATION_DATE,
773           LAST_UPDATED_BY,
774           LAST_UPDATE_DATE,
775           LAST_UPDATE_LOGIN)
776         values (
777           l_user_id,
778           'ICX_CUSTOMER_CONTACT_ID',
779           178,
780           l_customer_id,
781           owner_id,
782           sysdate,
783           owner_id,
784           sysdate,
785           owner_id);
786       end if;
787 
788       exception
789           when others then
790            fnd_message.set_name( 'FND','SQL_PLSQL_ERROR' );
791            fnd_message.set_token('ROUTINE', l_api_name);
792 	   fnd_message.set_token('ERRNO', SQLCODE);
793  	   fnd_message.set_token('REASON', SQLERRM);
794     end;
795   end if;
796 
797   if (l_supplier_id is not null) then
798     begin
799       update AK_WEB_USER_SEC_ATTR_VALUES set
800         NUMBER_VALUE = l_supplier_id,
801         LAST_UPDATED_BY = owner_id,
802         LAST_UPDATE_DATE = sysdate,
803         LAST_UPDATE_LOGIN = owner_id
804       where WEB_USER_ID = l_user_id
805       and ATTRIBUTE_CODE = 'ICX_SUPPLIER_CONTACT_ID'
806       and ATTRIBUTE_APPLICATION_ID = 178
807       and NUMBER_VALUE = l_old_supplier_id; -- bug 10371150
808 
809       if (sql%rowcount = 0) then
810         insert into AK_WEB_USER_SEC_ATTR_VALUES (
811           WEB_USER_ID,
812           ATTRIBUTE_CODE,
813           ATTRIBUTE_APPLICATION_ID,
814           NUMBER_VALUE,
815           CREATED_BY,
816           CREATION_DATE,
817           LAST_UPDATED_BY,
818           LAST_UPDATE_DATE,
819           LAST_UPDATE_LOGIN)
820         values (
821           l_user_id,
822           'ICX_SUPPLIER_CONTACT_ID',
823           178,
824           l_supplier_id,
825           owner_id,
826           sysdate,
827           owner_id,
828           sysdate,
829           owner_id);
830       end if;
831 
832       exception
833           when others then
834            fnd_message.set_name( 'FND','SQL_PLSQL_ERROR' );
835            fnd_message.set_token('ROUTINE', l_api_name);
836 	   fnd_message.set_token('ERRNO', SQLCODE);
837  	   fnd_message.set_token('REASON', SQLERRM);
838     end;
839   end if;
840 
841   -- Sync user change to LDAP
842   fnd_user_pkg.user_synch(x_user_name);
843 
844   -- Bug 8227171 UpdateUserInternal
845   -- Raise WF event oracle.apps.fnd.post.user.update
846   if (nvl(g_event_controller, 'XXXX') <> 'CREATE') then
847   begin
848 
849   -- Bug 14673409 - set the new_customer_id to be passed to the event if the association is changed.
850   -- Since supplier_id is not being derived will continue as is
851   if (l_old_person_party_id <> l_person_party_id) then
852         new_person_party_id := l_person_party_id;
853        if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
854            fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
855                      'Associating with new person_party_id: '||new_person_party_id);
856        end if;
857   end if;
858 
859     if (l_old_customer_id <> l_customer_id) then
860         new_customer_id := l_customer_id;
861        if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
862            fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
863                      'Associating with new customer_id: '||new_customer_id);
864        end if;
865     end if;
866 
867     if (l_old_employee_id <> l_employee_id) then
868         new_employee_id := l_employee_id;
869        if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
870            fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
871                      'Associating a new employee_id: '||new_employee_id);
872        end if;
873     end if;
874 
875     if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
876             fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
877                      'Raising event oracle.apps.fnd.post.user.update');
878             fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
879                      'Passing new_customer_id = '||new_customer_id||' new_person_party_id = '||new_person_party_id ||
880                              ' and new_employee_id = '||new_employee_id);
881    end if;
882 
883 
884     -- Bug 8683723
885     -- Passing some of the desired columns that may be updated to the Workflow
886     -- event in case of special handling requirements.
887     wf_event.AddParameterToList('NEW_EMAIL_ADDRESS', x_email_address, l_parameter_list);
888     wf_event.AddParameterToList('NEW_DESCRIPTION', x_description, l_parameter_list);
889     wf_event.AddParameterToList('NEW_CUSTOMER_ID', new_customer_id, l_parameter_list);
890     wf_event.AddParameterToList('NEW_FAX', x_fax, l_parameter_list);
891     wf_event.AddParameterToList('NEW_USER_GUID', x_user_guid, l_parameter_list);
892     wf_event.AddParameterToList('NEW_END_DATE', x_end_date, l_parameter_list);
893     wf_event.AddParameterToList('NEW_PERSON_PARTY_ID', new_person_party_id, l_parameter_list);
894     wf_event.AddParameterToList('NEW_SUPPLIER_ID', x_supplier_id, l_parameter_list);
895     wf_event.AddParameterToList('NEW_EMPLOYEE_ID', new_employee_id, l_parameter_list);
896     wf_event.raise(p_event_name =>'oracle.apps.fnd.post.user.update',
897                   p_event_key => l_user_id,
898                   p_event_data => NULL,
899                   p_parameters => l_parameter_list,
900                   p_send_date => Sysdate);
901     exception
902       when others then
903         reason := fnd_message.get_encoded;
904         if (reason is not null) then
905           fnd_message.set_encoded(reason);
906         else
907           fnd_message.set_name('FND', 'FND_RAISE_EVENT_FAILED');
908         end if;
909         app_exception.raise_exception;
910 
911   end;
912   end if;
913 
914 end UpdateUserInternal;
915 
916 ----------------------------------------------------------------------
917 --
918 -- LOAD_ROW (PRIVATE)
919 -- Overloaded version for backward compatibility only.
920 -- Use version below.
921 --
922 procedure LOAD_ROW (
923   X_USER_NAME                           in      VARCHAR2,
924   X_OWNER                               in      VARCHAR2,
925   X_ENCRYPTED_USER_PASSWORD             in      VARCHAR2,
926   X_SESSION_NUMBER                      in      VARCHAR2,
927   X_START_DATE                          in      VARCHAR2,
928   X_END_DATE                            in      VARCHAR2,
929   X_LAST_LOGON_DATE                     in      VARCHAR2,
930   X_DESCRIPTION                         in      VARCHAR2,
931   X_PASSWORD_DATE                       in      VARCHAR2,
932   X_PASSWORD_ACCESSES_LEFT              in      VARCHAR2,
933   X_PASSWORD_LIFESPAN_ACCESSES          in      VARCHAR2,
934   X_PASSWORD_LIFESPAN_DAYS              in      VARCHAR2,
935   X_EMAIL_ADDRESS                       in      VARCHAR2,
936   X_FAX                                 in      VARCHAR2 ) is
937 
938 begin
939       fnd_user_pkg.LOAD_ROW (
940         X_USER_NAME=>X_USER_NAME,
941         X_OWNER=> X_OWNER,
942         X_ENCRYPTED_USER_PASSWORD=>X_ENCRYPTED_USER_PASSWORD,
943         X_SESSION_NUMBER=> X_SESSION_NUMBER,
944         X_START_DATE=> X_START_DATE,
945         X_END_DATE=> X_END_DATE,
946         X_LAST_LOGON_DATE=> X_LAST_LOGON_DATE,
947         X_DESCRIPTION=> X_DESCRIPTION,
948         X_PASSWORD_DATE=> X_PASSWORD_DATE,
949         X_PASSWORD_ACCESSES_LEFT=> X_PASSWORD_ACCESSES_LEFT,
950         X_PASSWORD_LIFESPAN_ACCESSES=> X_PASSWORD_LIFESPAN_ACCESSES,
951         X_PASSWORD_LIFESPAN_DAYS=> X_PASSWORD_LIFESPAN_DAYS,
952         X_EMAIL_ADDRESS=> X_EMAIL_ADDRESS,
953         X_FAX=> X_FAX,
954         X_CUSTOM_MODE=> '',
955         X_LAST_UPDATE_DATE=> '');
956 
957 end LOAD_ROW;
958 
959 ----------------------------------------------------------------------
960 --
961 -- LOAD_ROW (PRIVATE)
962 --   Insert/update a new row of data.
963 --   Only for use by FNDLOAD, other apis should use LoadUser below.
964 --
965 procedure LOAD_ROW (
966   X_USER_NAME                           in      VARCHAR2,
967   X_OWNER                               in      VARCHAR2,
968   X_ENCRYPTED_USER_PASSWORD             in      VARCHAR2,
969   X_SESSION_NUMBER                      in      VARCHAR2,
970   X_START_DATE                          in      VARCHAR2,
971   X_END_DATE                            in      VARCHAR2,
972   X_LAST_LOGON_DATE                     in      VARCHAR2,
973   X_DESCRIPTION                         in      VARCHAR2,
974   X_PASSWORD_DATE                       in      VARCHAR2,
975   X_PASSWORD_ACCESSES_LEFT              in      VARCHAR2,
976   X_PASSWORD_LIFESPAN_ACCESSES          in      VARCHAR2,
977   X_PASSWORD_LIFESPAN_DAYS              in      VARCHAR2,
978   X_EMAIL_ADDRESS                       in      VARCHAR2,
979   X_FAX                                 in      VARCHAR2,
980   X_CUSTOM_MODE                         in      VARCHAR2,
981   X_LAST_UPDATE_DATE                    in      VARCHAR2,
982   X_PERSON_PARTY_NAME                   in      VARCHAR2 default NULL) is
983 
984   owner_id number := 0;
985   ret boolean;
986   f_luby    number;  -- entity owner in file
987   f_ludate  date;    -- entity update date in file
988   db_luby   number;  -- entity owner in db
989   db_ludate date;    -- entity update date in db
990   l_end_date date;
991   l_last_logon_date date;
992   l_password_date date;
993   l_password_accesses_left number;
994   l_password_lifespan_accesses number;
995   l_password_lifespan_days number;
996   l_person_party_id number;
997   l_party_type      varchar2(30);
998 
999 -- simple local proc to save redunant code - added for bug 3254311
1000 PROCEDURE DoPassword_update( puser_name in varchar2, pcrypt_pass in varchar2 ) is
1001   encPwd varchar2(100);
1002 BEGIN
1003     -- The insert/update didn't include the password, because
1004     -- those apis can't decrypt it.
1005     -- Set it directly now.
1006 
1007     -- NULL password means no update     -- bug 7687370
1008     if (pcrypt_pass is null) then
1009         return;
1010     end if;
1011 
1012     -- bug 4047740 - as a byproduct of FND_WEB_SEC.set_reencrypted_password
1013     -- NOT calling change_password we need this check to complete the checks
1014     -- below as in FND_WEB_SEC - also added update to both encrypted rows for
1015     -- the fnd_user update below for completeness.
1016     if(false = fnd_sso_manager.isPasswordChangeable(puser_name)) then
1017         encPwd := 'EXTERNAL';
1018     else
1019         encPwd := pcrypt_pass;
1020     end if;
1021 
1022     if (encPwd in ('EXTERNAL', 'INVALID')) then
1023         -- The password was 'EXTERNAL' or 'INVALID', just set it directly
1024         -- without trying to re-encrypt
1025         update fnd_user
1026         set encrypted_foundation_password = encPwd,
1027             encrypted_user_password = encPwd
1028         where user_name = puser_name;
1029 
1030         -- print warning in log file if it was 'INVALID'
1031         if (encPwd = 'INVALID') then
1032             fnd_file.put_line(fnd_file.Log,'Invalid password for user ' ||puser_name );
1033         end if;
1034     else
1035         ret := fnd_user_pkg.SetReEncryptedPassword(puser_name, encPwd, 'LOADER');
1036     end if;
1037 END;
1038 
1039 begin
1040   -- Translate owner to file_last_updated_by
1041   f_luby := fnd_load_util.owner_id(x_owner);
1042 
1043   -- Translate char last_update_date to date
1044   f_ludate := nvl(to_date(x_last_update_date, 'YYYY/MM/DD'), sysdate);
1045 
1046    /*Bug2896887 - Modified code to analyze and set up the correct value
1047                   for the nullable parameters to be passed to the
1048                   UpdateUser and CreateUser procedures. */
1049 
1050    if (X_END_DATE = fnd_user_pkg.null_char) then
1051         l_end_date := fnd_user_pkg.null_date;
1052    else -- bug 7311525 prevent upload of non-null end date for GUEST
1053        if (UPPER(x_user_name) <> 'GUEST') then
1054           l_end_date := to_date(X_END_DATE, 'YYYY/MM/DD');
1055        else
1056           l_end_date := null;
1057        end if;
1058    end if;
1059 
1060    if (X_PASSWORD_DATE = fnd_user_pkg.null_char) then
1061         l_password_date := fnd_user_pkg.null_date;
1062    else
1063         l_password_date := to_date(X_PASSWORD_DATE, 'YYYY/MM/DD');
1064    end if;
1065 
1066    if (X_LAST_LOGON_DATE = fnd_user_pkg.null_char) then
1067         l_last_logon_date := fnd_user_pkg.null_date;
1068    else
1069         l_last_logon_date := to_date(X_LAST_LOGON_DATE, 'YYYY/MM/DD');
1070    end if;
1071 
1072    if (X_PASSWORD_ACCESSES_LEFT = fnd_user_pkg.null_char) then
1073         l_password_accesses_left := fnd_user_pkg.null_number;
1074    else
1075         l_password_accesses_left := to_number(X_PASSWORD_ACCESSES_LEFT);
1076    end if;
1077 
1078    if (X_PASSWORD_LIFESPAN_ACCESSES = fnd_user_pkg.null_char) then
1079         l_password_lifespan_accesses := fnd_user_pkg.null_number;
1080    else
1081         l_password_lifespan_accesses := to_number(X_PASSWORD_LIFESPAN_ACCESSES);
1082    end if;
1083 
1084    if (X_PASSWORD_LIFESPAN_DAYS = fnd_user_pkg.null_char) then
1085         l_password_lifespan_days := fnd_user_pkg.null_number;
1086    else
1087         l_password_lifespan_days := to_number(X_PASSWORD_LIFESPAN_DAYS);
1088    end if;
1089 
1090   begin
1091     select LAST_UPDATED_BY, LAST_UPDATE_DATE
1092     into db_luby, db_ludate
1093     from FND_USER
1094     where USER_NAME = X_USER_NAME;
1095 
1096     /* PARTY */
1097     l_person_party_id := null;
1098     begin
1099       FND_OAM_USER_INFO.HZ_PARTY_NAME_TO_ID(x_person_party_name,
1100                                             l_person_party_id,
1101                                             l_party_type);
1102     exception
1103       when no_data_found then
1104         l_person_party_id := null;
1105     end;
1106 
1107     if (fnd_load_util.upload_test(f_luby, f_ludate, db_luby,
1108                                   db_ludate, X_CUSTOM_MODE)) then
1109         UpdateUserInternal(
1110             x_user_name => x_user_name,
1111             x_owner => x_owner,    -- bug 7687370
1112             x_unencrypted_password => '',
1113             x_session_number => to_number(x_session_number),
1114             x_start_date => to_date(X_START_DATE, 'YYYY/MM/DD'),
1115             x_end_date => L_END_DATE,
1116             x_last_logon_date => L_LAST_LOGON_DATE,
1117             x_description => X_DESCRIPTION,
1118             x_password_date => L_PASSWORD_DATE,
1119             x_password_accesses_left => L_PASSWORD_ACCESSES_LEFT,
1120             x_password_lifespan_accesses => L_PASSWORD_LIFESPAN_ACCESSES,
1121             x_password_lifespan_days => L_PASSWORD_LIFESPAN_DAYS,
1122             x_employee_id => null,
1123             x_email_address => x_email_address,
1124             x_fax => x_fax,
1125             x_customer_id => null,
1126             x_supplier_id => null,
1127             x_person_party_id => l_person_party_id,
1128             x_old_password => null,
1129             x_mode => 'EMPLOYEE',
1130             x_last_update_date => f_ludate);
1131 
1132         --  added for bug 3254311 by mskees
1133         DoPassword_update(X_USER_NAME, X_ENCRYPTED_USER_PASSWORD);
1134     end if;
1135   exception
1136     when no_data_found then
1137         -- bug 4047740 changed dummy password from 'welcome' to new FND_WEB_SEC
1138         -- constant, requires AFSCJAVS.pls 115.27 and AFSCJAVB.pls 115.63
1139         fnd_user_pkg.createuser(
1140             X_USER_NAME,
1141             X_OWNER,   -- bug 7687370
1142             FND_WEB_SEC.INVALID_PWD,
1143             to_number(X_SESSION_NUMBER),
1144             to_date(X_START_DATE, 'YYYY/MM/DD'),
1145             L_END_DATE,
1146             L_LAST_LOGON_DATE,
1147             X_DESCRIPTION,
1148             L_PASSWORD_DATE,
1149             L_PASSWORD_ACCESSES_LEFT,
1150             L_PASSWORD_LIFESPAN_ACCESSES,
1151             L_PASSWORD_LIFESPAN_DAYS,
1152             null,
1153             X_EMAIL_ADDRESS,
1154             X_FAX,
1155             null,
1156             null);
1157         --  added for bug 3254311 by mskees
1158         DoPassword_update(X_USER_NAME, X_ENCRYPTED_USER_PASSWORD);
1159   end;
1160 
1161 
1162 end LOAD_ROW;
1163 
1164 ----------------------------------------------------------------------
1165 --
1166 -- CreateUserIdInternal (PRIVATE)
1167 --   Internal wrapper for CreateUserId and CreateUserIdParty
1168 --
1169 function CreateUserIdInternal (
1170   x_user_name                  in varchar2,
1171   x_owner                      in varchar2,
1172   x_unencrypted_password       in varchar2,
1173   x_session_number             in number,
1174   x_start_date                 in date,
1175   x_end_date                   in date,
1176   x_last_logon_date            in date,
1177   x_description                in varchar2,
1178   x_password_date              in date,
1179   x_password_accesses_left     in number,
1180   x_password_lifespan_accesses in number,
1181   x_password_lifespan_days     in number,
1182   x_employee_id                in number,
1183   x_email_address              in varchar2,
1184   x_fax                        in varchar2,
1185   x_customer_id                in number,
1186   x_supplier_id                in number,
1187   x_person_party_id            in number,
1188   x_mode                       in varchar2,
1189   x_user_guid                  in raw default null,
1190   x_change_source              in number default null)
1191 return number is
1192   l_api_name varchar2(30):= 'CREATEUSERIDINTERNAL';
1193   owner_id number := 0;
1194   user_id number;
1195   ret varchar2(1) := 'N';
1196   reason varchar2(32000);
1197 
1198   pwd varchar2(100); /* 4351689 */
1199   l_user_guid raw(16);
1200   l_oid_pwd varchar2(30);
1201 
1202   l_expire_pwd pls_integer;
1203   l_password_date date;
1204   l_password_accesses_left number;
1205   l_password_lifespan_accesses number;
1206   l_password_lifespan_days number;
1207 
1208 begin
1209    if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
1210             fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
1211                      'Begin');
1212    end if;
1213 
1214   -- Bug 7687370
1215   if (x_owner is null) then
1216     owner_id := fnd_global.user_id;
1217   else
1218     owner_id := fnd_load_util.owner_id(x_owner);
1219   end if;
1220 
1221 
1222   begin
1223     -- Before creating the user, we should validate the user_name
1224     -- to make sure that there is no special characters.
1225     validate_user_name(x_user_name);
1226 
1227     /* bug 4351689 - allow the create functions to pass in null for
1228                      External password control*/
1229     pwd := nvl( x_unencrypted_password, FND_WEB_SEC.EXTERNAL_PWD );
1230 
1231     SAVEPOINT create_user;
1232 
1233     ret := fnd_web_sec.create_user(x_user_name,pwd,user_id);
1234 
1235     if (ret = 'Y') then
1236       -- Enhancement 5027812
1237       if ((x_change_source is null or
1238            x_change_source <> fnd_user_pkg.CHANGE_SOURCE_OID) and
1239           pwd <> fnd_web_sec.external_pwd) then
1240       -- We need to translate the external constant to null. Otherwise
1241       -- fnd_ldap_wrapper.create_user will use that constant as real password.
1242       if (pwd = fnd_web_sec.external_pwd) then
1243         pwd := '';
1244       end if;
1245 
1246         -- Bug#4118749 - Create user in OID
1247         if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
1248         fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
1249                      'Start calling ldap_wrapper_create_user');
1250         fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
1251                    'x_user_name = '||x_user_name);
1252         end if;
1253 
1254         begin
1255           -- 5235329, 5375111 Let ldap/oid know whether to expire password
1256           -- Bug 13595376 - Added condition to expire password for password_date in the past
1257           -- on user create as it was added for user update via bug 9285464
1258 
1259           -- Bug 13707735 - removed the condition that was added for bug 13595376
1260           -- this condition is incorrect - removed from both create and update flows.
1261           -- NOTE:  This condition should be the same as used in FND_SIGNON.IS_PWD_EXPIRED
1262 
1263           -- Bug 13713119 Decode the fnd_user_pkg.null_date and fnd_user_pkg.null_number
1264           -- values that may be passed to indicate a null.  These variables should only be
1265           -- used to calculate expiration and not passed to the UpdateUserInternal API - this API
1266           -- does its own calculation
1267 
1268          if (x_password_date = fnd_user_pkg.null_date) then
1269              l_password_date := null;
1270          else
1271              l_password_date := x_password_date;
1272          end if;
1273 
1274          if (x_password_accesses_left = fnd_user_pkg.null_number) then
1275              l_password_accesses_left := null;
1276          else
1277              l_password_accesses_left := x_password_accesses_left;
1278          end if;
1279 
1280          if (x_password_lifespan_accesses = fnd_user_pkg.null_number) then
1281              l_password_lifespan_accesses := null;
1282          else
1283              l_password_lifespan_accesses := x_password_lifespan_accesses;
1284          end if;
1285 
1286           if (x_password_lifespan_days = fnd_user_pkg.null_number) then
1287              l_password_lifespan_days := null;
1288          else
1289              l_password_lifespan_days := x_password_lifespan_days;
1290          end if;
1291 
1292 
1293           if (l_password_date is null  or
1294              (l_password_lifespan_accesses is not null
1295                and nvl(l_password_accesses_left, 0) < 1)  or
1296               (l_password_lifespan_days is not null and
1297                sysdate >= l_password_date + l_password_lifespan_days)) then
1298 
1299             if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
1300                  fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
1301                     'Call ldap_wrapper_create_user with expire_pwd flag=true');
1302             end if;
1303 
1304             l_expire_pwd := fnd_ldap_wrapper.G_TRUE;
1305           else
1306 
1307             if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
1308                 fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
1309                      'Call ldap_wrapper_create_user with expire_pwd flag=false');
1310             end if;
1311 
1312             l_expire_pwd := fnd_ldap_wrapper.G_FALSE;
1313           end if;
1314           -- end 5235329, 5375111
1315 
1316           -- Begin Bug 4318754, 4424225
1317           ldap_wrapper_create_user(upper(x_user_name), pwd, x_start_date,
1318                               x_end_date, x_description, x_email_address,
1319                               x_fax, l_expire_pwd, l_user_guid, l_oid_pwd);
1320           -- If wrapper gives back EXTERNAL password, we need to update
1321           -- the user with external password. l_oid_pwd will be used later
1322           -- in the UpdateUser call. setting to null means no change.
1323           if (l_oid_pwd <> fnd_web_sec.external_pwd) then
1324             l_oid_pwd := '';
1325           end if;
1326           -- End Bug 4318754, 4424225
1327         exception
1328           when others then
1329             ROLLBACK to create_user;
1330             reason := fnd_message.get();
1331             fnd_message.set_name('FND', 'FND_CREATE_USER_FAILED');
1332             fnd_message.set_token('USER_NAME', X_USER_NAME);
1333             fnd_message.set_token('REASON', reason);
1334             app_exception.raise_exception;
1335         end;
1336 
1337         if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
1338         fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
1339                      'After calling ldap_wrapper_create_user');
1340         end if;
1341       else
1342         l_user_guid := x_user_guid;
1343       end if;
1344 
1345       -- the createuser java code uses the user_id as created_by which
1346       -- is not correct. We must correct here.
1347       update fnd_user
1348       set created_by = owner_id
1349       where user_name = upper(x_user_name);
1350 
1351       -- update the rest of the data except password
1352       if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
1353       fnd_log.string(FND_LOG.LEVEL_STATEMENT,
1354      c_log_head || l_api_name || '.call_upduser',
1355         'CreateUser(): calling fnd_user_pkg.UpdateUser');
1356       end if;
1357 
1358       -- bug 8227171 Use the event controller global to tell the
1359       -- update user event not to fire since the create event will
1360       -- fire.
1361       g_event_controller := 'CREATE';
1362 
1363       -- NOTE:  This bit is using UpdateUser (rather than direct sql update)
1364       --        so that the user synch code in UpdateUser is triggered.
1365       --        Don't change this without taking that into account.
1366       --
1367       if (x_mode = 'PARTY') then
1368 --      fnd_user_pkg.UpdateUserParty(
1369 -- Begin bug 4318754, 4424225
1370 -- In order to handle user_guid, calls UpdateUserInternal directly
1371 -- instead of UpdateUserParty which does not take user_guid as argument.
1372         fnd_user_pkg.UpdateUserInternal(
1373 -- End bug 4318754, 4424225
1374           x_user_name => x_user_name,
1375           x_owner => x_owner,
1376           x_unencrypted_password => l_oid_pwd,
1377           x_session_number => x_session_number,
1378           x_start_date => x_start_date,
1379           x_end_date => x_end_date,
1380           x_last_logon_date => x_last_logon_date,
1381           x_description => x_description,
1382           x_password_date => x_password_date,
1383           x_password_accesses_left => x_password_accesses_left,
1384           x_password_lifespan_accesses => x_password_lifespan_accesses,
1385           x_password_lifespan_days => x_password_lifespan_days,
1386           x_employee_id => x_employee_id, -- 7311235 no need to pass null
1387           x_email_address => x_email_address,
1388           x_fax => x_fax,
1389           x_customer_id => x_customer_id, -- 7311235 no need to pass null
1390           x_supplier_id => x_supplier_id, -- 7311235 no need to pass null
1391           x_person_party_id => x_person_party_id,
1392           x_old_password => null,
1393           x_mode => 'PARTY',
1394           x_user_guid => l_user_guid,
1395           x_change_source => fnd_user_pkg.change_source_oid);
1396       else
1397         fnd_user_pkg.UpdateUser(
1398           x_user_name => x_user_name,
1399           x_owner => x_owner,
1400           x_unencrypted_password => l_oid_pwd,
1401           x_session_number => x_session_number,
1402           x_start_date => x_start_date,
1403           x_end_date => x_end_date,
1404           x_last_logon_date => x_last_logon_date,
1405           x_description => x_description,
1406           x_password_date => x_password_date,
1407           x_password_accesses_left => x_password_accesses_left,
1408           x_password_lifespan_accesses => x_password_lifespan_accesses,
1409           x_password_lifespan_days => x_password_lifespan_days,
1410           x_employee_id => x_employee_id,
1411           x_email_address => x_email_address,
1412           x_fax => x_fax,
1413           x_customer_id => x_customer_id,
1414           x_supplier_id => x_supplier_id,
1415           x_old_password => null,
1416           x_user_guid => l_user_guid,
1417           x_change_source => fnd_user_pkg.change_source_oid);
1418       end if;
1419 
1420       -- bug 8227171 CreateUserIdInternal
1421       -- Raise the WF event oracle.apps.fnd.post.user.create
1422       begin
1423          if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
1424             fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
1425                      'Raising oracle.apps.fnd.post.user.create event');
1426          end if;
1427          g_event_controller := NULL; -- we try once then reset
1428          wf_event.raise(p_event_name => 'oracle.apps.fnd.post.user.create',
1429                         p_event_key => to_char(user_id),
1430                         p_event_data => NULL,
1431                         p_send_date => Sysdate);
1432 
1433       exception
1434          when others then
1435           reason := fnd_message.get_encoded;
1436           if (reason is not null) then
1437             fnd_message.set_encoded(reason);
1438           else
1439             fnd_message.set_name('FND', 'FND_RAISE_EVENT_FAILED');
1440           end if;
1441           app_exception.raise_exception;
1442       end;
1443 
1444     else -- fnd_web_sec.create_user must have failed.
1445       -- The java layer puts message onto the message stack.
1446       reason := fnd_message.get();
1447       fnd_message.set_name('FND', 'FND_CREATE_USER_FAILED');
1448       fnd_message.set_token('USER_NAME', X_USER_NAME);
1449       fnd_message.set_token('REASON', reason);
1450       app_exception.raise_exception;
1451     end if;
1452 
1453     return (user_id);
1454    end;
1455 end CreateUserIdInternal;
1456 
1457 ----------------------------------------------------------------------
1458 --
1459 -- CreateUserId (PUBLIC)
1460 --   Insert new user record into FND_USER table.
1461 --   If that user exists already, exception raised with the error message.
1462 --   There are three input arguments must be provided. All the other columns
1463 --   in FND_USER table can take the default value.
1464 --
1465 --   *** NOTE: This version accepts the old customer_id/employee_id
1466 --   keys foreign keys to the "person".  Use CreateUserIdParty to create
1467 --   a user with the new person_party_id key.
1468 --
1469 -- Input (Mandatory)
1470 --  x_user_name:            The name of the new user
1471 --  x_owner:                'SEED' or 'CUST'(customer)
1472 --  x_unencrypted_password: The password for this new user
1473 -- Returns
1474 --   User_id of created user
1475 --
1476 function CreateUserId (
1477   x_user_name                  in varchar2,
1478   x_owner                      in varchar2,
1479   x_unencrypted_password       in varchar2 default null,
1480   x_session_number             in number default 0,
1481   x_start_date                 in date default sysdate,
1482   x_end_date                   in date default null,
1483   x_last_logon_date            in date default null,
1484   x_description                in varchar2 default null,
1485   x_password_date              in date default null,
1486   x_password_accesses_left     in number default null,
1487   x_password_lifespan_accesses in number default null,
1488   x_password_lifespan_days     in number default null,
1489   x_employee_id                in number default null,
1490   x_email_address              in varchar2 default null,
1491   x_fax                        in varchar2 default null,
1492   x_customer_id                in number default null,
1493   x_supplier_id                in number default null)
1494 return number is
1495 begin
1496   return CreateUserIdInternal(
1497     x_user_name => x_user_name,
1498     x_owner => x_owner,
1499     x_unencrypted_password => x_unencrypted_password,
1500     x_session_number => x_session_number,
1501     x_start_date => x_start_date,
1502     x_end_date => x_end_date,
1503     x_last_logon_date => x_last_logon_date,
1504     x_description => x_description,
1505     x_password_date => x_password_date,
1506     x_password_accesses_left => x_password_accesses_left,
1507     x_password_lifespan_accesses => x_password_lifespan_accesses,
1508     x_password_lifespan_days => x_password_lifespan_days,
1509     x_employee_id => x_employee_id,
1510     x_email_address => x_email_address,
1511     x_fax => x_fax,
1512     x_customer_id => x_customer_id,
1513     x_supplier_id => x_supplier_id,
1514     x_person_party_id => null,
1515     x_mode => 'EMPLOYEE');
1516 end CreateUserId;
1517 
1518 ----------------------------------------------------------------------
1519 --
1520 -- CreateUserIdParty (PUBLIC)
1521 --   Insert new user record into FND_USER table.
1522 --   If that user exists already, exception raised with the error message.
1523 --   There are three input arguments must be provided. All the other columns
1524 --   in FND_USER table can take the default value.
1525 --
1526 --   *** NOTE: This version accepts the new person_party_id foreign key
1527 --   to the "person".  Use CreateUserId to create a user with the old
1528 --   customer_id/employee_id keys.
1529 --
1530 -- Input (Mandatory)
1531 --  x_user_name:            The name of the new user
1532 --  x_owner:                'SEED' or 'CUST'(customer)
1533 --  x_unencrypted_password: The password for this new user
1534 -- Returns
1535 --   User_id of created user
1536 --
1537 function CreateUserIdParty (
1538   x_user_name                  in varchar2,
1539   x_owner                      in varchar2,
1540   x_unencrypted_password       in varchar2 default null,
1541   x_session_number             in number default 0,
1542   x_start_date                 in date default sysdate,
1543   x_end_date                   in date default null,
1544   x_last_logon_date            in date default null,
1545   x_description                in varchar2 default null,
1546   x_password_date              in date default null,
1547   x_password_accesses_left     in number default null,
1548   x_password_lifespan_accesses in number default null,
1549   x_password_lifespan_days     in number default null,
1550   x_email_address              in varchar2 default null,
1551   x_fax                        in varchar2 default null,
1552   x_person_party_id            in number default null)
1553 return number is
1554 begin
1555   return CreateUserIdInternal(
1556     x_user_name => x_user_name,
1557     x_owner => x_owner,
1558     x_unencrypted_password => x_unencrypted_password,
1559     x_session_number => x_session_number,
1560     x_start_date => x_start_date,
1561     x_end_date => x_end_date,
1562     x_last_logon_date => x_last_logon_date,
1563     x_description => x_description,
1564     x_password_date => x_password_date,
1565     x_password_accesses_left => x_password_accesses_left,
1566     x_password_lifespan_accesses => x_password_lifespan_accesses,
1567     x_password_lifespan_days => x_password_lifespan_days,
1568     x_employee_id => null,
1569     x_email_address => x_email_address,
1570     x_fax => x_fax,
1571     x_customer_id => null,
1572     x_supplier_id => null,
1573     x_person_party_id => x_person_party_id,
1574     x_mode => 'PARTY');
1575 end CreateUserIdParty;
1576 
1577 ----------------------------------------------------------------------
1578 --
1579 -- CreateUser (PUBLIC)
1580 --   Insert new user record into FND_USER table.
1581 --   If that user exists already, exception raised with the error message.
1582 --   There are three input arguments must be provided. All the other columns
1583 --   in FND_USER table can take the default value.
1584 --
1585 --   *** NOTE: This version accepts the old customer_id/employee_id
1586 --   keys foreign keys to the "person".  Use CreateUserParty to create
1587 --   a user with the new person_party_id key.
1588 --
1589 -- Input (Mandatory)
1590 --  x_user_name:            The name of the new user
1591 --  x_owner:                'SEED' or 'CUST'(customer)
1592 --  x_unencrypted_password: The password for this new user
1593 --
1594 procedure CreateUser (
1595   x_user_name                  in varchar2,
1596   x_owner                      in varchar2,
1597   x_unencrypted_password       in varchar2 default null,
1598   x_session_number             in number default 0,
1599   x_start_date                 in date default sysdate,
1600   x_end_date                   in date default null,
1601   x_last_logon_date            in date default null,
1602   x_description                in varchar2 default null,
1603   x_password_date              in date default null,
1604   x_password_accesses_left     in number default null,
1605   x_password_lifespan_accesses in number default null,
1606   x_password_lifespan_days     in number default null,
1607   x_employee_id                in number default null,
1608   x_email_address              in varchar2 default null,
1609   x_fax                        in varchar2 default null,
1610   x_customer_id                in number default null,
1611   x_supplier_id                in number default null)
1612 is
1613   dummy number;
1614 begin
1615   dummy := fnd_user_pkg.CreateUserId(
1616     x_user_name,
1617     x_owner,
1618     x_unencrypted_password,
1619     x_session_number,
1620     x_start_date,
1621     x_end_date,
1622     x_last_logon_date,
1623     x_description,
1624     x_password_date,
1625     x_password_accesses_left,
1626     x_password_lifespan_accesses,
1627     x_password_lifespan_days,
1628     x_employee_id,
1629     x_email_address,
1630     x_fax,
1631     x_customer_id,
1632     x_supplier_id);
1633 end CreateUser;
1634 
1635 ----------------------------------------------------------------------
1636 --
1637 -- CreateUserParty (PUBLIC)
1638 --   Insert new user record into FND_USER table.
1639 --   If that user exists already, exception raised with the error message.
1640 --   There are three input arguments must be provided. All the other columns
1641 --   in FND_USER table can take the default value.
1642 --
1643 --   *** NOTE: This version accepts the new person_party_id foreign key
1644 --   to the "person".  Use CreateUser to create a user with the old
1645 --   customer_id/employee_id keys.
1646 --
1647 -- Input (Mandatory)
1648 --  x_user_name:            The name of the new user
1649 --  x_owner:                'SEED' or 'CUST'(customer)
1650 --  x_unencrypted_password: The password for this new user
1651 --
1652 procedure CreateUserParty (
1653   x_user_name                  in varchar2,
1654   x_owner                      in varchar2,
1655   x_unencrypted_password       in varchar2 default null,
1656   x_session_number             in number default 0,
1657   x_start_date                 in date default sysdate,
1658   x_end_date                   in date default null,
1659   x_last_logon_date            in date default null,
1660   x_description                in varchar2 default null,
1661   x_password_date              in date default null,
1662   x_password_accesses_left     in number default null,
1663   x_password_lifespan_accesses in number default null,
1664   x_password_lifespan_days     in number default null,
1665   x_email_address              in varchar2 default null,
1666   x_fax                        in varchar2 default null,
1667   x_person_party_id            in number default null)
1668 is
1669   dummy number;
1670 begin
1671   dummy := fnd_user_pkg.CreateUserIdParty(
1672     x_user_name,
1673     x_owner,
1674     x_unencrypted_password,
1675     x_session_number,
1676     x_start_date,
1677     x_end_date,
1678     x_last_logon_date,
1679     x_description,
1680     x_password_date,
1681     x_password_accesses_left,
1682     x_password_lifespan_accesses,
1683     x_password_lifespan_days,
1684     x_email_address,
1685     x_fax,
1686     x_person_party_id);
1687 end CreateUserParty;
1688 
1689 ----------------------------------------------------------------------
1690 --
1691 -- UpdateUser (Public)
1692 --   Update any column for a particular user record. If that user does
1693 --   not exist, exception raised with error message.
1694 --   You can use this procedure to update a user's password for example.
1695 --
1696 --   *** NOTE: This version accepts the old customer_id/employee_id
1697 --   keys foreign keys to the "person".  Use UpdateUserParty to update
1698 --   a user with the new person_party_id key.
1699 --
1700 -- Usage Example in pl/sql
1701 --   begin fnd_user_pkg.updateuser('SCOTT', 'SEED', 'DRAGON'); end;
1702 --
1703 -- Mandatory Input Arguments
1704 --   x_user_name: An existing user name
1705 --   x_owner:     'SEED' or 'CUST'(customer)
1706 --
1707 procedure UpdateUser (
1708   x_user_name                  in varchar2,
1709   x_owner                      in varchar2,
1710   x_unencrypted_password       in varchar2 default null,
1711   x_session_number             in number default null,
1712   x_start_date                 in date default null,
1713   x_end_date                   in date default null,
1714   x_last_logon_date            in date default null,
1715   x_description                in varchar2 default null,
1716   x_password_date              in date default null,
1717   x_password_accesses_left     in number default null,
1718   x_password_lifespan_accesses in number default null,
1719   x_password_lifespan_days     in number default null,
1720   x_employee_id                in number default null,
1721   x_email_address              in varchar2 default null,
1722   x_fax                        in varchar2 default null,
1723   x_customer_id                in number default null,
1724   x_supplier_id                in number default null,
1725   x_old_password               in varchar2 default null)
1726 is
1727 begin
1728   UpdateUserInternal(
1729     x_user_name => x_user_name,
1730     x_owner => x_owner,
1731     x_unencrypted_password => x_unencrypted_password,
1732     x_session_number => x_session_number,
1733     x_start_date => x_start_date,
1734     x_end_date => x_end_date,
1735     x_last_logon_date => x_last_logon_date,
1736     x_description => x_description,
1737     x_password_date => x_password_date,
1738     x_password_accesses_left => x_password_accesses_left,
1739     x_password_lifespan_accesses => x_password_lifespan_accesses,
1740     x_password_lifespan_days => x_password_lifespan_days,
1741     x_employee_id => x_employee_id,
1742     x_email_address => x_email_address,
1743     x_fax => x_fax,
1744     x_customer_id => x_customer_id,
1745     x_supplier_id => x_supplier_id,
1746     x_person_party_id => null,
1747     x_old_password => x_old_password,
1748     x_mode => 'EMPLOYEE');
1749 end UpdateUser;
1750 
1751 ----------------------------------------------------------------------
1752 --
1753 -- UpdateUserParty (Public)
1754 --   Update any column for a particular user record. If that user does
1755 --   not exist, exception raised with error message.
1756 --   You can use this procedure to update a user's password for example.
1757 --
1758 --   *** NOTE: This version accepts the new person_party_id foreign key
1759 --   to the "person".  Use UpdateUser to update a user with the old
1760 --   customer_id/employee_id keys.
1761 --
1762 -- Usage Example in pl/sql
1763 --   begin fnd_user_pkg.updateuser('SCOTT', 'SEED', 'DRAGON'); end;
1764 --
1765 -- Mandatory Input Arguments
1766 --   x_user_name: An existing user name
1767 --   x_owner:     'SEED' or 'CUST'(customer)
1768 --
1769 procedure UpdateUserParty (
1770   x_user_name                  in varchar2,
1771   x_owner                      in varchar2,
1772   x_unencrypted_password       in varchar2 default null,
1773   x_session_number             in number default null,
1774   x_start_date                 in date default null,
1775   x_end_date                   in date default null,
1776   x_last_logon_date            in date default null,
1777   x_description                in varchar2 default null,
1778   x_password_date              in date default null,
1779   x_password_accesses_left     in number default null,
1780   x_password_lifespan_accesses in number default null,
1781   x_password_lifespan_days     in number default null,
1782   x_email_address              in varchar2 default null,
1783   x_fax                        in varchar2 default null,
1784   x_person_party_id            in number default null,
1785   x_old_password               in varchar2 default null)
1786 is
1787 begin
1788   UpdateUserInternal(
1789     x_user_name => x_user_name,
1790     x_owner => x_owner,
1791     x_unencrypted_password => x_unencrypted_password,
1792     x_session_number => x_session_number,
1793     x_start_date => x_start_date,
1794     x_end_date => x_end_date,
1795     x_last_logon_date => x_last_logon_date,
1796     x_description => x_description,
1797     x_password_date => x_password_date,
1798     x_password_accesses_left => x_password_accesses_left,
1799     x_password_lifespan_accesses => x_password_lifespan_accesses,
1800     x_password_lifespan_days => x_password_lifespan_days,
1801     x_employee_id => null,
1802     x_email_address => x_email_address,
1803     x_fax => x_fax,
1804     x_customer_id => null,
1805     x_supplier_id => null,
1806     x_person_party_id => x_person_party_id,
1807     x_old_password => x_old_password,
1808     x_mode => 'PARTY');
1809 end UpdateUserParty;
1810 
1811 ----------------------------------------------------------------------------
1812 --
1813 -- LoadUser (Public)
1814 --   Create or Update user, as appropriate.
1815 --
1816 --   *** NOTE: This version accepts the old customer_id/employee_id
1817 --   keys foreign keys to the "person".  Use LoadUserParty to load
1818 --   a user with the new person_party_id key.
1819 --
1820 procedure LoadUser(
1821   x_user_name                  in varchar2,
1822   x_owner                      in varchar2,
1823   x_unencrypted_password       in varchar2 default null,
1824   x_session_number             in number default null,
1825   x_start_date                 in date default null,
1826   x_end_date                   in date default null,
1827   x_last_logon_date            in date default null,
1828   x_description                in varchar2 default null,
1829   x_password_date              in date default null,
1830   x_password_accesses_left     in number default null,
1831   x_password_lifespan_accesses in number default null,
1832   x_password_lifespan_days     in number default null,
1833   x_employee_id                in number default null,
1834   x_email_address              in varchar2 default null,
1835   x_fax                        in varchar2 default null,
1836   x_customer_id                in number default null,
1837   x_supplier_id                in number default null) /* PARTY */
1838 is
1839   l_api_name varchar2(30) := 'LOADUSER';
1840   exists_flag varchar2(1);
1841   reason varchar2(32000);
1842 begin
1843 
1844   if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
1845   fnd_log.string(FND_LOG.LEVEL_STATEMENT,
1846                      c_log_head || l_api_name || '.before_updstmnt',
1847                      'LoadUser(): before update statement');
1848   end if;
1849   begin
1850     select 'Y'
1851     into exists_flag
1852     from fnd_user u
1853     where u.user_name = x_user_name;
1854   exception
1855     when no_data_found then
1856       exists_flag := 'N';
1857   end;
1858 
1859   if (exists_flag = 'Y') then
1860     fnd_user_pkg.UpdateUser(x_user_name,
1861                           x_owner,
1862                           x_unencrypted_password,
1863                           x_session_number,
1864                           x_start_date,
1865                           x_end_date,
1866                           x_last_logon_date,
1867                           x_description,
1868                           x_password_date,
1869                           x_password_accesses_left,
1870                           x_password_lifespan_accesses,
1871                           x_password_lifespan_days,
1872                           x_employee_id,
1873                           x_email_address,
1874                           x_fax,
1875                           x_customer_id,
1876                           x_supplier_id,
1877                           null);
1878   else  -- Must be new user
1879     -- insert the new user if x_session_number and x_start_date are provided
1880     if (x_unencrypted_password is not null) then
1881 
1882       if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
1883         fnd_log.string(FND_LOG.LEVEL_STATEMENT,
1884                      c_log_head || l_api_name || '.call_creatuser',
1885                     'LoadUser(): calling CreateUser');
1886       end if;
1887       fnd_user_pkg.createuser(x_user_name,
1888                           x_owner,
1889                           x_unencrypted_password,
1890                           x_session_number,
1891                           x_start_date,
1892                           x_end_date,
1893                           x_last_logon_date,
1894                           x_description,
1895                           x_password_date,
1896                           x_password_accesses_left,
1897                           x_password_lifespan_accesses,
1898                           x_password_lifespan_days,
1899                           x_employee_id,
1900                           x_email_address,
1901                           x_fax,
1902                           x_customer_id,
1903                           x_supplier_id);
1904     else
1905       fnd_message.set_name('FND', 'FND_NO_PASSWORD_PROVIDED');
1906       fnd_message.set_token('USER_NAME', X_USER_NAME);
1907       fnd_message.set_token('ROUTINE', 'FND_USER_PKG.LOADUSER');
1908       app_exception.raise_exception;
1909     end if;
1910   end if;
1911 end LoadUser;
1912 
1913 ----------------------------------------------------------------------------
1914 --
1915 -- LoadUserParty (Public)
1916 --   Create or Update user, as appropriate.
1917 --
1918 --   *** NOTE: This version accepts the new person_party_id foreign key
1919 --   to the "person".  Use LoadUser to load a user with the old
1920 --   customer_id/employee_id keys.
1921 --
1922 procedure LoadUserParty(
1923   x_user_name                  in varchar2,
1924   x_owner                      in varchar2,
1925   x_unencrypted_password       in varchar2 default null,
1926   x_session_number             in number default null,
1927   x_start_date                 in date default null,
1928   x_end_date                   in date default null,
1929   x_last_logon_date            in date default null,
1930   x_description                in varchar2 default null,
1931   x_password_date              in date default null,
1932   x_password_accesses_left     in number default null,
1933   x_password_lifespan_accesses in number default null,
1934   x_password_lifespan_days     in number default null,
1935   x_email_address              in varchar2 default null,
1936   x_fax                        in varchar2 default null,
1937   x_person_party_id            in number default null)
1938 is
1939   l_api_name varchar2(30) := 'LOADUSERPARTY';
1940   exists_flag varchar2(1);
1941   reason varchar2(32000);
1942 begin
1943 
1944   if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
1945   fnd_log.string(FND_LOG.LEVEL_STATEMENT,
1946                      c_log_head || l_api_name || '.before_updstmnt',
1947                      'LoadUser(): before update statement');
1948   end if;
1949   begin
1950     select 'Y'
1951     into exists_flag
1952     from fnd_user u
1953     where u.user_name = x_user_name;
1954   exception
1955     when no_data_found then
1956       exists_flag := 'N';
1957   end;
1958 
1959   if (exists_flag = 'Y') then
1960     fnd_user_pkg.UpdateUserParty(x_user_name,
1961                           x_owner,
1962                           x_unencrypted_password,
1963                           x_session_number,
1964                           x_start_date,
1965                           x_end_date,
1966                           x_last_logon_date,
1967                           x_description,
1968                           x_password_date,
1969                           x_password_accesses_left,
1970                           x_password_lifespan_accesses,
1971                           x_password_lifespan_days,
1972                           x_email_address,
1973                           x_fax,
1974                           x_person_party_id,
1975                           null);
1976   else  -- Must be new user
1977     -- insert the new user if x_session_number and x_start_date are provided
1978     if (x_unencrypted_password is not null) then
1979 
1980       if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
1981       fnd_log.string(FND_LOG.LEVEL_STATEMENT,
1982                      c_log_head || l_api_name || '.call_creatuser',
1983                     'LoadUser(): calling CreateUser');
1984       end if;
1985       fnd_user_pkg.createuserparty(x_user_name,
1986                           x_owner,
1987                           x_unencrypted_password,
1988                           x_session_number,
1989                           x_start_date,
1990                           x_end_date,
1991                           x_last_logon_date,
1992                           x_description,
1993                           x_password_date,
1994                           x_password_accesses_left,
1995                           x_password_lifespan_accesses,
1996                           x_password_lifespan_days,
1997                           x_email_address,
1998                           x_fax,
1999                           x_person_party_id);
2000     else
2001       fnd_message.set_name('FND', 'FND_NO_PASSWORD_PROVIDED');
2002       fnd_message.set_token('USER_NAME', X_USER_NAME);
2003       fnd_message.set_token('ROUTINE', 'FND_USER_PKG.LOADUSER');
2004       app_exception.raise_exception;
2005     end if;
2006   end if;
2007 end LoadUserParty;
2008 
2009 ----------------------------------------------------------------------------
2010 --
2011 -- DisableUser (PUBLIC)
2012 --   Sets end_date to sysdate for a given user. This is to terminate that user.
2013 --   You longer can log in as this user anymore. If username is not valid,
2014 --   exception raised with error message.
2015 --
2016 -- Usage example in pl/sql
2017 --   begin fnd_user_pkg.disableuser('SCOTT'); end;
2018 --
2019 -- Input (Mandatory)
2020 --  username:       User Name
2021 --
2022 procedure DisableUser(username varchar2) is
2023 begin
2024 --  bug 3043856 phase 1 of long term plan on Guest User
2025 --  here we do not disable Guest account
2026   if( upper(username) = 'GUEST' ) then
2027       return;
2028   end if;
2029   fnd_user_pkg.UpdateUser(x_user_name => DisableUser.username,
2030                           x_owner     => null,
2031                           x_end_date  => sysdate);
2032 end DisableUser;
2033 ----------------------------------------------------------------------------
2034 --
2035 -- ValidateLogin (PUBLIC)
2036 --   Test if password is good for this given user.
2037 --
2038 -- Usage example in pl/sql
2039 --   begin fnd_user_pkg.validatelogin('SCOTT', 'TIGER'); end;
2040 --
2041 -- Input (Mandatory)
2042 --  username:       User Name
2043 --  password:       User Password
2044 --
2045 function ValidateLogin(username   varchar2,
2046                        password   varchar2) return boolean is
2047 begin
2048   return boolRet(fnd_web_sec.validate_login(username, password));
2049 end ValidateLogin;
2050 ----------------------------------------------------------------------------
2051 --
2052 -- ValidateSSOLogin (RESTRICTED)
2053 -- Validates the given username/password against SSO
2054 -- This routine is restricted and can ONLY be used with the explicit permission
2055 -- from ATG/AOL management.
2056 -- Any other use will NOT be supported by AOLJ/SSO development team!!!!!!!
2057 --
2058 -- This api is introduced to enable the clients which can NOT perform HTTP
2059 -- authentication against SSO (NON-UI business logic).
2060 
2061 -- Use the api for SSO user authentication.   It is assumed that EBS is already
2062 -- configured with SSO.
2063 -- In all other cases use FND_USER_PKG.ValidateLogin.
2064 -- Product teams who are currently using this api:
2065 -- Oracle Mobile Field Service  (FND_APPLICATION.APPLICATION_SHORT_NAME=CSM)
2066 -- (bug#14057306)
2067 
2068 function ValidateSSOLogin(username   varchar2,
2069                        password   varchar2) return boolean is
2070 begin
2071   return fnd_ldap_wrapper.validate_login(username, password);
2072 end ValidateSSOLogin;
2073 
2074 ----------------------------------------------------------------------------
2075 --
2076 -- ChangePassword (PUBLIC)
2077 --   Set new password for a given user without having to provide
2078 --   the old password.
2079 --
2080 -- Usage example in pl/sql
2081 --   begin fnd_user_pkg.changepassword('SCOTT', 'WELCOME'); end;
2082 --
2083 -- Input (Mandatory)
2084 --  username:       User Name
2085 --  newpassword     New Password
2086 --
2087 function ChangePassword(username      varchar2,
2088                         newpassword   varchar2) return boolean is
2089 begin
2090   return boolRet(fnd_web_sec.Change_Password(username, newpassword, FALSE));
2091 end;
2092 ----------------------------------------------------------------------------
2093 --
2094 -- ChangePassword (PUBLIC)
2095 --   Set new password for a given user if the existing password needed to be
2096 --   validated before changing to the new password.
2097 --
2098 -- Usage example in pl/sql
2099 --   begin fnd_user_pkg.changepassword('SCOTT', 'TIGER', 'WELCOME'); end;
2100 --
2101 -- Input (Mandatory)
2102 --  username:       User Name
2103 --  oldpassword     Old Password
2104 --  newpassword     New Password
2105 --
2106 function ChangePassword(username      varchar2,
2107                         oldpassword   varchar2,
2108                         newpassword   varchar2) return boolean is
2109 
2110 begin
2111    return boolRet(fnd_web_sec.Change_Password(username, oldpassword,
2112                                              newpassword, newpassword, FALSE));
2113 end;
2114 ----------------------------------------------------------------------------
2115 --
2116 -- GetReEncryptedPassword (PUBLIC)
2117 --   Return user password encrypted with new key. This just returns the
2118 --   newly encrypted password. It does not set the password in FND_USER table.
2119 --
2120 -- Usage example in pl/sql
2121 --   declare
2122 --     newpass varchar2(100);
2123 --   begin
2124 --     newpass := fnd_user_pkg.getreencryptedpassword('SCOTT', 'NEWKEY'); end;
2125 --   end;
2126 --
2127 -- Input (Mandatory)
2128 --   username:  User Name
2129 --   newkey     New Key
2130 --
2131 function GetReEncryptedPassword(username varchar2,
2132                                 newkey   varchar2) return varchar2 is
2133 begin
2134   return (fnd_web_sec.get_reencrypted_password(username, newkey));
2135 end;
2136 
2137 ----------------------------------------------------------------------------
2138 -- SetReEncryptedPassword (PUBLIC)
2139 --   Set user password from value returned from GetReEncryptedPassword.
2140 --   This is to update column ENCRYPTED_USER_PASSWORD in table FND_USER
2141 --
2142 -- Usage example in pl/sql
2143 --   declare
2144 --     newpass varchar2(100);
2145 --   begin
2146 --     newpass := fnd_user_pkg.getreencryptedpassword('SCOTT', 'NEWKEY'); end;
2147 --     fnd_user_pkg.setreencryptedpassword('SCOTT', newpass, 'NEWKEY'); end;
2148 --   end;
2149 --
2150 -- Input (Mandatory)
2151 --  username:       User Name
2152 --  reencpwd:       Reencrypted Password
2153 --  newkey          New Key
2154 --
2155 function SetReEncryptedPassword(username varchar2,
2156                               reencpwd varchar2,
2157                               newkey   varchar2) return boolean is
2158 begin
2159   return boolRet(fnd_web_sec.set_reencrypted_password(username,reencpwd,newkey));
2160 end;
2161 ----------------------------------------------------------------------------
2162 -- MergeCustomer (PUBLIC)
2163 --   This is the procedure being called during the Party Merge.
2164 --   FND_USER.MergeCustomer() has been registered in Party Merge Data Dict.
2165 --   The input/output arguments format matches the document PartyMergeDD.doc.
2166 --   The goal is to fix the customer id in fnd_user table to point to the
2167 --   same party when two similar parties are begin merged.
2168 --
2169 -- Usage example in pl/sql
2170 --   This procedure should only be called from the PartyMerge utility.
2171 --
2172 procedure MergeCustomer(p_entity_name in varchar2,
2173                         p_from_id in number,
2174                         p_to_id in out nocopy number,
2175                         p_from_fk_id in number,
2176                         p_to_fk_id in number,
2177                         p_parent_entity_name in varchar2,
2178                         p_batch_id in number,
2179                         p_batch_party_id in number,
2180                         p_return_status in out nocopy varchar2) is
2181 begin
2182   p_return_status := FND_API.G_RET_STS_SUCCESS;
2183 
2184   if (p_from_fk_id <> p_to_fk_id) then
2185 
2186     update fnd_user
2187     set customer_id = p_to_fk_id
2188     where customer_id = p_from_fk_id;
2189 
2190     -- Added for Function Security Cache Invalidation
2191     fnd_function_security_cache.update_user(p_from_id);
2192 
2193   end if;
2194 
2195 end MergeCustomer;
2196 
2197 --------------------------------------------------------------------------
2198 --
2199 -- user_change - The rule function for FND's subscription on the
2200 --               oracle.apps.wf.entmgr.user.change event.  This function
2201 --               retrieves the user's information and updates the
2202 --               corresponding fnd_user as needed, if the user exists.
2203 --
2204 FUNCTION user_change(p_subscription_guid in            raw,
2205                      p_event             in out nocopy wf_event_t)
2206 return varchar2 is
2207   my_ent_type  varchar2(50);
2208   my_username  varchar2(256); -- one-way code only
2209   my_mode      varchar2(256); -- one-way code only
2210   my_cachekey  varchar2(256);
2211   my_user      varchar2(256);
2212   my_user_id   number;
2213   l_allow_sync varchar2(1);
2214   l_local_login varchar(10);
2215   l_profile_defined boolean;
2216   my_guid      varchar2(256);
2217   old_desc     varchar2(256);
2218   new_desc     varchar2(256);
2219   old_email    varchar2(256);
2220   new_email    varchar2(256);
2221   old_fax      varchar2(256);
2222   new_fax      varchar2(256);
2223   new_email2   varchar2(256); -- one-way code only
2224   new_fax2     varchar2(256); -- one-way code only
2225   new_desc2    varchar2(256); -- one-way code only
2226   l_api_name     varchar2(30) := 'user_change';
2227 
2228   old_guid     raw(16);
2229 
2230   cursor existing_users(userGuid in varchar2) is
2231     select nvl(description,   '*NULL*'),
2232            nvl(email_address, '*NULL*'),
2233            nvl(fax,           '*NULL*'),
2234            user_name,
2235            user_id
2236     from   fnd_user
2237     where  user_guid = userGuid;
2238 
2239 begin
2240 
2241   if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
2242     fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2243                  'Start user_change');
2244     fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2245                  'p_subscription_guid ='||p_subscription_guid);
2246     fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2247                  'event_name ='||p_event.GetEventName);
2248     fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2249                  'parameter CHANGE_SOURCE ='||
2250                   p_event.GetValueForParameter('CHANGE_SOURCE'));
2251   end if;
2252 
2253   -- Ignore our own changes
2254   if (p_event.GetValueForParameter('CHANGE_SOURCE') = 'FND_USR') then
2255     return 'SUCCESS';
2256 
2257   -- If CHANGE_SOURCE is LDAP, it means it's raised from one-way sync code.
2258   elsif (p_event.GetValueForParameter('CHANGE_SOURCE') = 'LDAP') then
2259 
2260     my_username := p_event.GetEventKey();
2261     my_mode := p_event.GetValueForParameter('CHANGE_TYPE');
2262 
2263     if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
2264       fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2265                  'LDAP - event_key ='||my_username);
2266       fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2267                 'LDAP - parameter CHANGE_TYPE ='||my_mode);
2268     end if;
2269 
2270     if (my_mode = 'DELETE') then
2271       begin
2272         fnd_user_pkg.disableUser(my_username);
2273       exception
2274         when others then null;
2275       end;
2276 
2277     elsif (my_mode in ('ADD','MODIFY','LOAD')) then
2278       --
2279       -- First check to see if user exists and get the existing attribute
2280       -- values.  If the user does not exist, we're done.
2281       -- Convert nulls to *NULL* so that old values are either *NULL*
2282       -- or an actual value.
2283       --
2284       begin
2285         select nvl(description,   '*NULL*'),
2286                nvl(email_address, '*NULL*'),
2287                nvl(fax,           '*NULL*'),
2288                user_guid
2289         into   old_desc, old_email, old_fax, old_guid
2290         from   fnd_user
2291         where  user_name = my_username;
2292       exception
2293         when others then return 'SUCCESS';
2294       end;
2295 
2296       --
2297       -- Fetch the new values from the attribute cache
2298       -- New values can either be *NULL*, *UNKNOWN*, or an actual value
2299       --
2300       my_ent_type := wf_entity_mgr.get_entity_type(p_event.GetEventName());
2301 
2302       --     NOTE:  While we have the ability to distinguish between null
2303       --            and "known to be null", the standard apis do not.
2304       --            For now, we're must pass null regardless which is
2305       --            treated as a "don't change".  We do not yet support
2306       --            the ability to "null out" an attribute value.
2307 
2308       new_desc  := wf_entity_mgr.get_attribute_value(my_ent_type, my_username,
2309                                                   'DESCRIPTION');
2310       new_email := wf_entity_mgr.get_attribute_value(my_ent_type, my_username,
2311                                                   'MAIL');
2312       new_fax   := wf_entity_mgr.get_attribute_value(my_ent_type, my_username,
2313                                                   'FACSIMILETELEPHONENUMBER');
2314       --
2315       -- Determine if there are any changes to the attributes we're
2316       -- interested in.  And if so, update the user record.
2317       --
2318 
2319       if (wf_entity_mgr.isChanged(new_desc,  old_desc)   OR
2320           wf_entity_mgr.isChanged(new_email, old_email)  OR
2321           wf_entity_mgr.isChanged(new_fax,   old_fax))  then
2322 
2323         -- at least one of the attributes has changed -> update the user --
2324 
2325         --
2326         -- NOTE:  the following conversions are necessary until we resolve
2327         -- null and "null out"
2328         --
2329 --Start bug 3147423 change null to null_char
2330         if (new_desc = '*NULL*' or new_desc = '*UNKNOWN*') then
2331           new_desc2 := null_char;
2332         else
2333           new_desc2 := new_desc;
2334         end if;
2335 
2336         if (new_fax = '*NULL*' or new_fax = '*UNKNOWN*') then
2337           new_fax2 := null_char;
2338         else
2339           new_fax2 := new_fax;
2340         end if;
2341 
2342         if (new_email = '*NULL*' or new_email = '*UNKNOWN*') then
2343           new_email2 := null_char;
2344         else
2345           new_email2 := new_email;
2346         end if;
2347 --End bug 3147423
2348         -- end of conversions --
2349 
2350         fnd_user_pkg.UpdateUser(
2351           x_user_name     => my_username,
2352           x_owner         => 'CUST',
2353           x_description   => new_desc2,
2354           x_email_address => new_email2,
2355           x_fax           => new_fax2,
2356 -- This api is called by LDAP so pass the change source so that we don't
2357 -- start the synch loop.
2358           x_user_guid     => old_guid,
2359           x_change_source => fnd_user_pkg.change_source_oid);
2360 
2361       if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
2362         fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2363                   'LDAP - finished fnd_user_pkg.UpdateUser('||my_username||')');
2364       end if;
2365       end if;
2366     end if;
2367 
2368    -- If CHANGE_SOURCE is OID, it means it's raised from two-way sync code.
2369   elsif (p_event.GetValueForParameter('CHANGE_SOURCE') = 'OID') then
2370 
2371     my_cachekey := p_event.GetEventKey();
2372     my_ent_type := wf_entity_mgr.get_entity_type(p_event.GetEventName());
2373     my_guid     := wf_entity_mgr.get_attribute_value(my_ent_type, my_cachekey,
2374                                                   'ORCLGUID');
2375     if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
2376       fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2377                  'OID - event_key ='||my_cachekey);
2378       fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2379                  'OID - entity_type ='||my_ent_type);
2380       fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2381                  'OID - guid ='||my_guid);
2382     end if;
2383 
2384     open existing_users(my_guid);
2385     LOOP
2386       FETCH existing_users INTO old_desc, old_email, old_fax, my_user, my_user_id;
2387       EXIT WHEN existing_users%NOTFOUND;
2388 
2389       fnd_profile.get_specific(name_z => 'APPS_SSO_LDAP_SYNC',
2390                                user_id_z => my_user_id,
2391                                val_z => l_allow_sync,
2392                                defined_z => l_profile_defined);
2393 
2394       fnd_profile.get_specific(name_z => 'APPS_SSO_LOCAL_LOGIN',
2395                                user_id_z => my_user_id,
2396                                val_z => l_local_login,
2397                                defined_z => l_profile_defined);
2398 
2399       -- Don't sync users who have 'N' for profile value APPS_SSO_LDAP_SYNC
2400       -- or 'LOCAL' for profile value APPS_SSO_LOCAL_LOGIN
2401 
2402       if ( (l_allow_sync = 'Y') and (l_local_login <> 'LOCAL') ) then
2403 
2404         if (p_event.GetValueForParameter('CHANGE_TYPE') = 'DELETE') then
2405           begin
2406             fnd_user_pkg.disableUser(my_user);
2407           exception
2408             when others then null;
2409           end;
2410 
2411         else
2412           --
2413           -- Fetch the new values from the attribute cache.
2414           -- New values will be *NULL*, *UNKNOWN*, or an actual value.
2415           --
2416           --     NOTE:  While we have the ability to distinguish between null
2417           --            and "known to be null", the standard apis do not.
2418           --            For now, we're must pass null regardless which is
2419           --            treated as a "don't change".  fnd_user_pkg apis do
2420           --            not yet support the ability to "null out" an
2421           --            attribute value.  Weak.
2422           --
2423           new_desc  := wf_entity_mgr.get_attribute_value(my_ent_type, my_cachekey,
2424                                                    'DESCRIPTION');
2425           new_email := wf_entity_mgr.get_attribute_value(my_ent_type, my_cachekey,
2426                                                    'MAIL');
2427           new_fax   := wf_entity_mgr.get_attribute_value(my_ent_type, my_cachekey,
2428                                                    'FACSIMILETELEPHONENUMBER');
2429           --
2430           -- Determine if there are any changes to the attributes we're
2431           -- interested in.  And if so, update the user record.
2432           --
2433           if (wf_entity_mgr.isChanged(new_desc,  old_desc)   OR
2434               wf_entity_mgr.isChanged(new_email, old_email)  OR
2435               wf_entity_mgr.isChanged(new_fax,   old_fax)) then
2436 --Start Bug 3147423
2437             if (new_desc in ('*NULL*', '*UNKNOWN*')) then
2438                 new_desc := null_char;
2439             end if;
2440 
2441             if (new_fax in ('*NULL*', '*UNKNOWN*')) then
2442               new_fax := null_char;
2443             end if;
2444 
2445             if (new_email in ('*NULL*', '*UNKNOWN*')) then
2446               new_email := null_char;
2447             end if;
2448 
2449             fnd_user_pkg.UpdateUser(
2450               x_user_name     => my_user,
2451               x_owner         => 'CUST',
2452               x_description   => new_desc,
2453               x_email_address => new_email,
2454               x_fax           => new_fax);
2455 
2456             if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
2457               fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2458                   'OID - finished fnd_user_pkg.UpdateUser('||my_user||')');
2459       end if;
2460           end if;
2461         end if;
2462       else
2463         null;
2464       end if;
2465     END LOOP;
2466     CLOSE existing_users;
2467   end if;
2468 
2469   if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
2470     fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2471                  'End user_change');
2472   end if;
2473   return wf_rule.default_rule(p_subscription_guid, p_event);
2474 end user_change;
2475 
2476 --------------------------------------------------------------------------
2477 --
2478 -- user_create_rf - The rule function for FND's 2nd subscription on the
2479 --               oracle.apps.wf.entmgr.user.change event.  This function
2480 --               retrieves the user's information and creates the
2481 --               corresponding fnd_user if the user does not already exist.
2482 --
2483 FUNCTION user_create_rf(p_subscription_guid in            raw,
2484                         p_event             in out nocopy wf_event_t)
2485          return varchar2
2486 is
2487   my_ent_type   varchar2(50);
2488   my_cachekey   varchar2(256);
2489   my_username   varchar2(256); -- one-way code only
2490   existing_user varchar2(1);
2491   new_desc      varchar2(256);
2492   new_email     varchar2(256);
2493   new_fax       varchar2(256);
2494   new_guid      varchar2(256);
2495   new_email2    varchar2(256); -- one-way code only
2496   new_fax2      varchar2(256); -- one-way code only
2497   new_desc2     varchar2(256); -- one-way code only
2498   l_api_name     varchar2(30) := 'user_create_rf';
2499 
2500 begin
2501 
2502   if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
2503     fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2504                  'Start user_create_rf');
2505     fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2506                  'p_subscription_guid ='||p_subscription_guid);
2507     fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2508                  'event_name ='||p_event.GetEventName);
2509     fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2510                  'parameter CHANGE_SOURCE ='||
2511                   p_event.GetValueForParameter('CHANGE_SOURCE'));
2512   end if;
2513   -- Ignore our own changes
2514   if (p_event.GetValueForParameter('CHANGE_SOURCE') = 'FND_USR') then
2515     return 'SUCCESS';
2516 
2517   -- If CHANGE_SOURCE is LDAP, it means it's raised from one-way sync code.
2518   elsif (p_event.GetValueForParameter('CHANGE_SOURCE') = 'LDAP') then
2519     my_username := p_event.GetEventKey();
2520 
2521     if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
2522       fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2523                  'LDAP - event_key ='||my_username);
2524     end if;
2525 
2526     begin
2527       select 'Y' into existing_user
2528       from   fnd_user
2529       where  user_name = my_username;
2530 
2531       return 'SUCCESS';
2532     exception
2533       when others then
2534 
2535       -- user doesn't exist yet, we have work to do --
2536       my_ent_type := wf_entity_mgr.get_entity_type(p_event.GetEventName());
2537 
2538       if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
2539         fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2540                   'LDAP - entity_type ='||my_ent_type);
2541       end if;
2542 
2543       --
2544       -- Fetch the new values from the attribute cache
2545       -- New values can either be *NULL*, *UNKNOWN*, or an actual value
2546       --
2547       new_desc  := wf_entity_mgr.get_attribute_value(my_ent_type, my_username,
2548                                                   'DESCRIPTION');
2549       new_email := wf_entity_mgr.get_attribute_value(my_ent_type, my_username,
2550                                                   'MAIL');
2551       new_fax   := wf_entity_mgr.get_attribute_value(my_ent_type, my_username,
2552                                                   'FACSIMILETELEPHONENUMBER');
2553       --
2554       -- NOTE:  the following conversions are necessary until we resolve
2555       -- null and "null out"
2556       --
2557 --Start Bug 3147423
2558       if (new_desc = '*NULL*' or new_desc = '*UNKNOWN*') then
2559         new_desc2 := null_char;
2560       else
2561         new_desc2 := new_desc;
2562       end if;
2563 
2564       if (new_fax = '*NULL*' or new_fax = '*UNKNOWN*') then
2565         new_fax2 := null_char;
2566       else
2567         new_fax2 := new_fax;
2568       end if;
2569 
2570       if (new_email = '*NULL*' or new_email = '*UNKNOWN*') then
2571         new_email2 := null_char;
2572       else
2573         new_email2 := new_email;
2574       end if;
2575 
2576 --End Bug 3147423
2577 
2578       -- end of conversions --
2579 
2580       fnd_user_pkg.CreateUser(
2581         x_user_name            => my_username,
2582         x_owner                => 'CUST',
2583         x_unencrypted_password => null,
2584         x_description          => new_desc2,
2585         x_email_address        => new_email2,
2586         x_fax                  => new_fax2);
2587 
2588       if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
2589         fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2590                   'LDAP - finished fnd_user_pkg.CreateUser('||my_username||')');
2591       end if;
2592     end;
2593 
2594   -- If CHANGE_SOURCE is OID, it means it's raised from two-way sync code.
2595   elsif (p_event.GetValueForParameter('CHANGE_SOURCE') = 'OID') then
2596 
2597     my_cachekey := p_event.GetEventKey();
2598     my_ent_type := wf_entity_mgr.get_entity_type(p_event.GetEventName());
2599     new_guid := wf_entity_mgr.get_attribute_value(my_ent_type, my_cachekey,
2600                                                 'ORCLGUID');
2601     if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
2602       fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2603                  'OID - event_key ='||my_cachekey);
2604       fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2605                  'OID - entity_type ='||my_ent_type);
2606       fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2607                  'OID - guid ='||new_guid);
2608     end if;
2609     begin
2610       select 'Y' into existing_user
2611       from   fnd_user
2612       where  user_name = my_cachekey;
2613 
2614     return 'SUCCESS';
2615 
2616     exception
2617       when others then  -- CREATE NEW USER --
2618 
2619       new_desc  := wf_entity_mgr.get_attribute_value(my_ent_type, my_cachekey,
2620                                                   'DESCRIPTION');
2621       new_email := wf_entity_mgr.get_attribute_value(my_ent_type, my_cachekey,
2622                                                   'MAIL');
2623       new_fax   := wf_entity_mgr.get_attribute_value(my_ent_type, my_cachekey,
2624                                                   'FACSIMILETELEPHONENUMBER');
2625       if (new_desc in ('*NULL*', '*UNKNOWN*')) then
2626         new_desc := null;
2627       end if;
2628 
2629       if (new_fax in ('*NULL*', '*UNKNOWN*')) then
2630         new_fax := null;
2631       end if;
2632 
2633       if (new_email in ('*NULL*', '*UNKNOWN*')) then
2634         new_email := null;
2635       end if;
2636 
2637       fnd_user_pkg.CreateUser(
2638         x_user_name            => my_cachekey,
2639         x_owner                => 'CUST',
2640         x_unencrypted_password => null,
2641         x_description          => new_desc,
2642         x_email_address        => new_email,
2643         x_fax                  => new_fax);
2644 
2645       if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
2646         fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2647                   'OID - finished fnd_user_pkg.CreateUser('||my_cachekey||')');
2648       end if;
2649 
2650       --
2651       -- guid will eventually be managed centrally so didn't want to add it
2652       -- to the fnd_user_pkg apis...hence the separate update here
2653       --
2654       update fnd_user set user_guid = new_guid
2655       where user_name = my_cachekey;
2656 
2657     end;
2658   end if;
2659 
2660   if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
2661     fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2662                  'End user_create_rf');
2663   end if;
2664 
2665   return wf_rule.default_rule(p_subscription_guid, p_event);
2666 end user_create_rf;
2667 
2668 -- Private
2669 -- Called by user_synch when user_name is changed
2670 procedure UpdateUserNameChildren(old_name in varchar2,
2671                                  new_name in varchar2) is
2672   colnames fnd_dictionary_pkg.NameArrayTyp;
2673   colold fnd_dictionary_pkg.NameArrayTyp;
2674   colnew fnd_dictionary_pkg.NameArrayTyp;
2675   l_api_name  CONSTANT varchar2(30) := 'UpdateUsernameChildren';
2676   tmpbuf varchar2(240);
2677   reason varchar2(2000);
2678   ret boolean;
2679 begin
2680   -- need to call pk update to do cascade foreign key children update
2681   colnames(0) := 'USER_NAME';
2682   colnames(1) := '';
2683   colold(0) := old_name;
2684   colold(1) := '';
2685   colnew(0) := new_name;
2686   colnew(1) := '';
2687 
2688   tmpbuf := 'Start calling fnd_dictionary_pkg.updatepkcolumns('||
2689              old_name||','||new_name||')';
2690   if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
2691   fnd_log.string(FND_LOG.LEVEL_STATEMENT, C_LOG_HEAD || l_api_name || '.',
2692                tmpbuf);
2693   end if;
2694   ret := fnd_dictionary_pkg.updatepkcolumns('FND', 'FND_USER', colnames, colold,
2695                                        colnew);
2696   tmpbuf := 'Finished fnd_dictionary_pkg.updatepkcolumns';
2697   if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
2698   fnd_log.string(FND_LOG.LEVEL_STATEMENT, C_LOG_HEAD || l_api_name || '.',
2699                tmpbuf);
2700   end if;
2701 exception
2702   when others then
2703     reason := fnd_message.get;
2704     fnd_message.set_name('FND', 'FND_FAILED_UPDATE_UNAME_CHILD');
2705     fnd_message.set_token('OLD_NAME', old_name);
2706     fnd_message.set_token('NEW_NAME', new_name);
2707     fnd_message.set_token('REASON', reason);
2708     app_exception.raise_exception;
2709 end UpdateUserNameChildren;
2710 --------------------------------------------------------------------------
2711 --
2712 -- user_synch - The centralized routine for communicating user changes
2713 --             with wf and entity mgr.
2714 --
2715 PROCEDURE user_synch(p_user_name in varchar2) is
2716   my_userid number;
2717   my_email  varchar2(240);
2718   my_desc   varchar2(240);
2719   my_fax    varchar2(80);
2720   my_pwd    varchar2(100);
2721   my_empid  number;
2722   my_partyid number;
2723   my_exp    date;
2724   my_start  date;
2725   my_guid   varchar2(32);
2726   myList    wf_parameter_list_t;
2727   ch_exp    varchar2(20);
2728   ch_start  varchar2(20);
2729   --<rwunderl:3203225>
2730   l_defined_z BOOLEAN;
2731   myLang      VARCHAR2(240);
2732   myTerr      VARCHAR2(240);
2733   l_userNTFPref   VARCHAR2(8); -- bug 3280951
2734   l_party_type    varchar2(30);
2735   --</rwunderl:3203225>
2736   dummy     number(1);
2737   -- <bug 2850261 (enhancement request) >
2738   ptyName varchar2(360);
2739   --</bug 2852061>
2740 
2741   l_api_name varchar2(30) := 'UserSynch';
2742 
2743 begin
2744   -- fetch info for synch --
2745 
2746   if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
2747     fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2748                    'Start user_synch');
2749     fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2750                    'p_user_name = '||p_user_name);
2751   end if;
2752 
2753   select user_id, email_address, description, fax, employee_id,
2754          person_party_id,
2755          start_date, end_date, user_guid, encrypted_user_password,
2756          to_char(start_date, 'YYYYMMDDHH24MISS'),
2757          to_char(end_date, 'YYYYMMDDHH24MISS')
2758   into   my_userid, my_email, my_desc, my_fax, my_empid, my_partyid,
2759          my_start, my_exp, my_guid, my_pwd, ch_start, ch_exp
2760   from   fnd_user
2761   where  user_name = upper(p_user_name);
2762 
2763   -- construct attribute list for wf synch --
2764   -- unstubbed the code
2765   wf_event.AddParameterToList('MAIL', my_email, mylist);
2766   wf_event.AddParameterToList('DESCRIPTION', my_desc, mylist);
2767   wf_event.AddParameterToList('FACSIMILETELEPHONENUMBER', my_fax, mylist);
2768   wf_event.AddParameterToList('USER_NAME', upper(p_user_name), mylist);
2769   wf_event.AddParameterToList('CN', upper(p_user_name), mylist);
2770   wf_event.AddParameterToList('SN', upper(p_user_name), mylist);
2771   wf_event.AddParameterToList('ORCLACTIVESTARTDATE', ch_start, mylist);
2772   if ((my_exp is null) OR
2773      (trunc(sysdate) between my_start and my_exp)) then
2774     wf_event.AddParameterToList('ORCLISENABLED', 'ACTIVE', mylist);
2775   else
2776     wf_event.AddParameterToList('ORCLISENABLED', 'INACTIVE', mylist);
2777   end if;
2778   wf_event.AddParameterToList('ORCLACTIVEENDDATE', ch_exp, mylist);
2779   wf_event.AddParameterToList('ORCLGUID', my_guid, mylist);
2780   -- bug 4318754
2781 
2782   wf_event.AddParameterToList('OLD_ORCLGUID', g_old_user_guid, mylist);
2783   -- end bug 4318754
2784 
2785   wf_event.AddParameterToList('USERPASSWORD', my_pwd, mylist);
2786   wf_event.AddParameterToList('PER_PERSON_ID',
2787                   fnd_number.number_to_canonical(my_empid), mylist);
2788   wf_event.AddParameterToList('PERSON_PARTY_ID',
2789                   fnd_number.number_to_canonical(my_partyid), mylist);
2790   -- bug 4318754
2791   wf_event.AddParameterToList('OLD_PERSON_PARTY_ID',
2792                  fnd_number.number_to_canonical(g_old_person_party_id), mylist);
2793   -- end bug 4318754
2794 
2795   -- begin 2850261
2796   begin
2797     FND_OAM_USER_INFO.HZ_PARTY_ID_TO_NAME(my_partyid, ptyName, l_party_type);
2798   exception
2799     when no_data_found then
2800       ptyName := p_user_name;
2801   end;
2802   wf_event.AddParameterToList('DISPLAYNAME', upper(ptyName), mylist);
2803   -- end 2852061
2804 
2805   -- begin bug 2504562
2806   wf_event.AddParameterToList('OLD_USER_NAME', g_old_user_name, mylist);
2807   /* set g_old_user_name to null here to cover calls to user_synch initiated
2808      from Forms or from the fnd_user_pkg.change_user_name PL/SQL api */
2809   --Comment out this following call because I need it to do the pk children
2810   --later. After pk children update, then I will reset g_old_user_name.
2811   --dummy := fnd_user_pkg.set_old_user_name(NULL);
2812   -- end bug 2504562
2813 
2814   -- <rwunderl:3203225>
2815   -- Added calls for the lang/territory and notification preference.
2816   fnd_profile.get_specific(name_z=>'ICX_LANGUAGE', user_id_z=>my_userid,
2817                            val_z=>myLang, defined_z=>l_defined_z);
2818   wf_event.AddParameterToList('PREFERREDLANGUAGE', myLang, myList);
2819 
2820   fnd_profile.get_specific(name_z=>'ICX_TERRITORY', user_id_z=>my_userid,
2821                            val_z=>myTerr, defined_z=>l_defined_z);
2822 
2823   wf_event.AddParameterToList('ORCLNLSTERRITORY', myTerr, myList);
2824 
2825   -- begin bug 3280951
2826   -- Retrieve the notification preference for the user
2827   -- using substr since fnd_preference.get returns varchar2(240)
2828   -- and this maps to varchar2(8) column on WF side.
2829   l_userNTFPref := substr(fnd_preference.get(UPPER(p_user_name), 'WF', 'MAILTYPE'), 1, 8);
2830 
2831   if (l_userNTFPref is NULL) then
2832     --There is no preference for the user, so retrieving the global.
2833     l_userNTFPref := substr(fnd_preference.get('-WF_DEFAULT-', 'WF', 'MAILTYPE'), 1, 8);
2834 
2835   end if;
2836 
2837   wf_event.AddParameterToList('ORCLWORKFLOWNOTIFICATIONPREF',
2838                               nvl(l_userNTFPref, 'MAILHTML'), mylist);
2839 
2840   -- end bug 3280951
2841 
2842   --Bug 3277794
2843   --Add the over-write parameter to the attribute list
2844   wf_event.AddParameterToList('WFSYNCH_OVERWRITE','TRUE',mylist);
2845 
2846   -- </rwunderl:3203225>
2847 
2848   if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
2849     fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2850                    'Calling wf_local_synch.propagate_user');
2851     fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2852                    'ORCLGUID = '|| my_guid);
2853     fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2854                    'PER_PERSON_ID = '|| my_empid);
2855     fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2856                    'PERSON_PARTY_ID = '|| my_partyid);
2857     fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2858                    'DISPLAY_NAME(PARTY_NAME) = '|| ptyName);
2859     fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2860                    'OLD_USER_NAME = '|| g_old_user_name);
2861   end if;
2862   -- update wf and the entity manager --
2863   wf_local_synch.propagate_user('FND_USR',my_userid, myList, my_start, my_exp);
2864   -- end of unstub
2865 
2866   if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
2867     fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2868                    'Finished wf_local_synch.propagate_user');
2869   end if;
2870   -- -----------------------------------------------------------------
2871   -- since wf_local_synch is temporarily stubbed out, also make the
2872   -- direct calls to entity-mgr to compensate (jvc)
2873   -- -----------------------------------------------------------------
2874 
2875   -- don't make this call anymore - code unstubbed
2876 
2877 --  wf_entity_mgr.put_attribute_value('USER', upper(p_user_name),
2878 --                                     'MAIL', my_email);
2879 --  wf_entity_mgr.put_attribute_value('USER', upper(p_user_name),
2880 --                                     'DESCRIPTION', my_desc);
2881 --  wf_entity_mgr.put_attribute_value('USER', upper(p_user_name),
2882 --                                     'FACSIMILETELEPHONENUMBER', my_fax);
2883 --  wf_entity_mgr.put_attribute_value('USER', upper(p_user_name),
2884 --                                     'USER_NAME', upper(p_user_name));
2885 --  wf_entity_mgr.put_attribute_value('USER', upper(p_user_name),
2886 --                                     'SN', upper(p_user_name));
2887 --  wf_entity_mgr.put_attribute_value('USER', upper(p_user_name),
2888 --                                     'ORCLACTIVESTARTDATE', ch_start);
2889 --  wf_entity_mgr.put_attribute_value('USER', upper(p_user_name),
2890 --                                     'ORCLACTIVEENDDATE', ch_exp);
2891 --  wf_entity_mgr.put_attribute_value('USER', upper(p_user_name),
2892 --                                     'ORCLGUID', my_guid);
2893 --  wf_entity_mgr.put_attribute_value('USER', upper(p_user_name),
2894 --                                     'USERPASSWORD', my_pwd);
2895 --  wf_entity_mgr.put_attribute_value('USER', upper(p_user_name),
2896 --                                     'PER_PERSON_ID',
2897 --                            fnd_number.number_to_canonical(my_empid));
2898 --  wf_entity_mgr.process_changes('USER', upper(p_user_name), 'FND_USR');
2899 
2900   -- Added for bug 3804617
2901   -- If a user_name is changed, we need to update all foreign key children.
2902   if (g_old_user_name is not null) then
2903     UpdateUsernameChildren(g_old_user_name, p_user_name);
2904   end if;
2905   -- set g_old_user_name to null here to cover calls to user_synch initiated
2906   -- from Forms or from the fnd_user_pkg.change_user_name PL/SQL api
2907   dummy := fnd_user_pkg.set_old_user_name(NULL);
2908   dummy := fnd_user_pkg.set_old_person_party_id(NULL);
2909   dummy := fnd_user_pkg.set_old_user_guid(NULL);
2910 
2911   if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
2912     fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
2913                    'End user_synch');
2914   end if;
2915 exception
2916 --  Bug 3617474: This NO_DATA_FOUND exception handler was placed in the event
2917 --  that fnd_user_pkg.user_synch() was passed an invalid or null user_name,
2918 --  i.e a user_name that does not exist in fnd_user.
2919     when NO_DATA_FOUND then
2920         null;
2921 
2922 end user_synch;
2923 
2924 --------------------------------------------------------------------------
2925 --
2926 -- DelResp (PUBLIC)
2927 --   Detach a responsibility which is currently attached to this given user.
2928 --   If any of the username or application short name or responsibility key or
2929 --   security group is not valid, exception raised with error message.
2930 --
2931 -- Usage example in pl/sql
2932 --   begin fnd_user_pkg.delresp('SCOTT', 'FND', 'APPLICATION_DEVELOPER',
2933 --                              'STANDARD'); end;
2934 -- Input (Mandatory)
2935 --  username:       User Name
2936 --  resp_app:       Application Short Name
2937 --  resp_key:       Responsibility Key
2938 --  security_group: Security Group Key
2939 --
2940 procedure DelResp(username       varchar2,
2941                   resp_app       varchar2,
2942                   resp_key       varchar2,
2943                   security_group varchar2) is
2944   userid number := -1;
2945   respid number := -1;
2946   appid  number := -1;
2947   secid  number := -1;
2948   startdate date;
2949 begin
2950   begin
2951     select user_id into userid
2952     from   fnd_user
2953     where  user_name = DelResp.username;
2954 
2955     select application_id into appid
2956     from   fnd_application
2957     where  application_short_name = DelResp.Resp_app;
2958 
2959     /* Bug4600645 - Modified to get actual start_date instead of using */
2960     /* sysdate in call to fnd_user_resp_groups_api.update_assignment   */
2961 
2962     select responsibility_id
2963      into respid
2964     from   fnd_responsibility
2965     where  application_id = appid
2966     and    responsibility_key = DelResp.resp_key;
2967 
2968     select security_group_id into secid
2969     from   fnd_security_groups
2970     where  security_group_key = DelResp.security_group;
2971 
2972    /*Bug4600645 - Get actual start_date value*/
2973 
2974     select start_date into startdate
2975     from fnd_user_resp_groups_all
2976     where user_id = userid
2977     and responsibility_id = respid
2978     and responsibility_application_id = appid;
2979 
2980   exception
2981     when no_data_found then
2982       fnd_message.set_token('USER_NAME', username);
2983       fnd_message.set_name('FND', 'INVALID_RESPONSIBILITY_DATA');
2984       fnd_message.set_token('APPS_NAME', resp_app);
2985       fnd_message.set_token('RESP_KEY', resp_key);
2986       fnd_message.set_token('SECURITY_GROUP', security_group);
2987       app_exception.raise_exception;
2988   end;
2989 
2990   if (fnd_user_resp_groups_api.assignment_exists(
2991                   userid, respid, appid, secid)) then
2992     fnd_user_resp_groups_api.update_assignment(
2993       user_id                        => userid,
2994       responsibility_id              => respid,
2995       responsibility_application_id  => appid,
2996       security_group_id              => secid,
2997       start_date                     => startdate,
2998       end_date                       => sysdate,
2999       description                    => null);
3000   end if;
3001 end DelResp;
3002 
3003 --------------------------------------------------------------------------
3004 --
3005 -- AddResp (PUBLIC)
3006 --   For a given user, attach a valid responsibility.
3007 --   If user name or application short name or responsbility key name
3008 --   or security group key is not valid, exception raised with error message.
3009 --
3010 -- Usage example in pl/sql
3011 --   begin fnd_user_pkg.addresp('SCOTT', 'FND', 'APPLICATION_DEVELOPER',
3012 --                              'STANDARD', 'DESCRIPTION', sysdate, null); end;
3013 -- Input (Mandatory)
3014 --  username:       User Name
3015 --  resp_app:       Application Short Name
3016 --  resp_key:       Responsibility Key
3017 --  security_group: Security Group Key
3018 --  description:    Description
3019 --  start_date:     Start Date
3020 --  end_date:       End Date
3021 --
3022 procedure AddResp(username       varchar2,
3023                   resp_app       varchar2,
3024                   resp_key       varchar2,
3025                   security_group varchar2,
3026                   description    varchar2,
3027                   start_date     date,
3028                   end_date       date) is
3029   userid number := -1;
3030   respid number := -1;
3031   appid  number := -1;
3032   secid  number := -1;
3033 begin
3034 
3035   begin
3036     select user_id into userid
3037     from   fnd_user
3038     where  user_name = AddResp.username;
3039 
3040     select application_id into appid
3041     from   fnd_application
3042     where  application_short_name = AddResp.resp_app;
3043 
3044     select responsibility_id into respid
3045     from   fnd_responsibility
3046     where  application_id = appid
3047     and    responsibility_key = AddResp.resp_key;
3048 
3049     select security_group_id into secid
3050     from   fnd_security_groups
3051     where  security_group_key = AddResp.security_group;
3052 
3053     exception
3054     when no_data_found then
3055       fnd_message.set_token('USER_NAME', username);
3056       fnd_message.set_name('FND', 'INVALID_RESPONSIBILITY_DATA');
3057       fnd_message.set_token('APPS_NAME', resp_app);
3058       fnd_message.set_token('RESP_KEY', resp_key);
3059       fnd_message.set_token('SECURITY_GROUP', security_group);
3060       app_exception.raise_exception;
3061   end;
3062 
3063   if (fnd_user_resp_groups_api.assignment_exists(
3064                      userid, respid, appid, secid)) then
3065        fnd_user_resp_groups_api.update_assignment(
3066          user_id                        => userid,
3067          responsibility_id              => respid,
3068          responsibility_application_id  => appid,
3069          security_group_id              => secid,
3070          start_date                     => AddResp.start_date,
3071          end_date                       => AddResp.end_date,
3072          description                    => AddResp.description);
3073   else
3074        fnd_user_resp_groups_api.insert_assignment(
3075          user_id                        => userid,
3076          responsibility_id              => respid,
3077          responsibility_application_id  => appid,
3078          security_group_id              => secid,
3079          start_date                     => AddResp.start_date,
3080          end_date                       => AddResp.end_date,
3081          description                    => AddResp.description);
3082   end if;
3083 
3084 end AddResp;
3085 
3086 -------------------------------------------------------------------
3087 -- Name:        isPasswordChangeable
3088 -- Description: Checks if user us externally authenticatied
3089 ----------------------------------------------------------------------
3090 Function isPasswordChangeable(
3091   p_user_name in varchar2)
3092 return boolean
3093 is
3094 begin
3095   return(fnd_sso_manager.isPasswordChangeable(p_user_name));
3096 end isPasswordChangeable;
3097 
3098 -------------------------------------------------------------------
3099 -- Name:        UpdatePassword_WF
3100 -- Description: Calls FND_USER_PKG.UpdateUser
3101 -------------------------------------------------------------------
3102  Procedure UpdatePassword_WF(itemtype  in varchar2,
3103                              itemkey   in varchar2,
3104                              actid     in number,
3105                              funcmode  in varchar2,
3106                              resultout in out nocopy varchar2) is
3107 
3108   begin
3109 
3110     if (funcmode = 'RUN') then
3111       FND_USER_PKG.UpdateUser(
3112            x_user_name=>
3113              WF_ENGINE.GetActivityAttrText(itemtype, itemkey, actid,
3114                                            'X_USER_NAME'),
3115            x_owner=>'CUST',
3116            x_unencrypted_password=>
3117              WF_ENGINE.GetActivityAttrText(itemtype, itemkey, actid,
3118                                                 'X_UNENCRYPTED_PASSWORD',
3119                                                 TRUE),
3120            x_password_date=>
3121              WF_ENGINE.GetActivityAttrDate(itemtype, itemkey, actid,
3122                                                 'X_PASSWORD_DATE', TRUE),
3123            x_password_accesses_left=>
3124              WF_ENGINE.GetActivityAttrNumber(itemtype, itemkey, actid,
3125                                                 'X_PASSWORD_ACCESSES_LEFT',
3126                                                 TRUE),
3127          x_password_lifespan_accesses=>
3128             WF_ENGINE.GetActivityAttrNumber(itemtype, itemkey, actid,
3129                                                 'X_PASSWORD_LIFESPAN_ACCESSES',
3130                                                 TRUE),
3131            x_password_lifespan_days=>
3132              WF_ENGINE.GetActivityAttrNumber(itemtype, itemkey, actid,
3133                                                 'X_PASSWORD_LIFESPAN_DAYS',
3134                                                 TRUE));
3135 
3136       resultout := WF_ENGINE.eng_completed || ':' || WF_ENGINE.eng_null;
3137 
3138     else
3139       resultout := WF_ENGINE.eng_completed || ':' || WF_ENGINE.eng_null;
3140 
3141     end if;
3142 
3143   exception
3144     when others then
3145       Wf_Core.Context('FND_WF_STANDARD', 'UpdatePassword', itemtype, itemkey,
3146                       actid);
3147       raise;
3148 end;
3149 
3150 ----------------------------------------------------------------------------
3151 --
3152 -- DERIVE_PERSON_PARTY_ID
3153 --   Derive the person_party_id, given a customer_id and employee_id
3154 -- IN
3155 --   user_name - User name (used for error messages)
3156 --   customer_id - Customer_id
3157 --   employee_id - Employee_id
3158 -- RETURNS
3159 --   person_party_id - Derived party_id
3160 --
3161 Function DERIVE_PERSON_PARTY_ID(
3162   user_name in varchar2,
3163   customer_id in number,
3164   employee_id in number,
3165   log_exception in varchar2 default 'Y')
3166 return number is
3167   l_api_name constant varchar2(30) := 'DERIVE_PERSON_PARTY_ID';
3168   l_employee_id number;
3169   l_customer_id number;
3170   l_cust_person_party_id number;
3171   l_cust_person_party_name varchar2(360);
3172   l_emp_person_party_id number;
3173   l_emp_person_party_name varchar2(360);
3174   l_party_type  varchar2(30);
3175   l_party_name  varchar2(360);
3176   l_err_to_raise boolean;
3177 begin
3178   --  if we have the value cached, just return the cached value.
3179   if (    (   (z_customer_id = customer_id)
3180            or (z_customer_id is null and customer_id is null))
3181       and (   (z_employee_id = employee_id)
3182            or (z_employee_id is null and employee_id is null))) then
3183     return z_person_party_id;
3184   end if;
3185 
3186   l_employee_id := employee_id;
3187   l_customer_id := customer_id;
3188   l_cust_person_party_id := NULL;
3189   l_emp_person_party_id := NULL;
3190 
3191   -- *** Derive party for customer_id ***
3192   if (l_customer_id is not NULL) then
3193     -- Get party type of current customer_id
3194     begin
3195       FND_OAM_USER_INFO.HZ_PARTY_ID_TO_NAME(l_customer_id,
3196                                             l_party_name, l_party_type);
3197     exception
3198       when no_data_found then
3199         if (log_exception = 'Y') then
3200            fnd_message.set_name('FND', 'USER_INVALID_CUSTOMER');
3201            fnd_message.set_token('USER', user_name);
3202            fnd_message.set_token('CUSTID', l_customer_id);
3203            if (fnd_log.LEVEL_EXCEPTION >= fnd_log.g_current_runtime_level) then
3204             fnd_log.message(FND_LOG.LEVEL_EXCEPTION,
3205               c_log_head || l_api_name || '.not_in_hz_parties', FALSE);
3206            end if;
3207            app_exception.raise_exception;
3208         else
3209            return null;
3210         end if;
3211     end;
3212 
3213     if (l_party_type = 'PERSON') then
3214       -- Customer_id is already party, just copy value to party_id
3215       l_cust_person_party_id := l_customer_id;
3216     elsif (l_party_type = 'PARTY_RELATIONSHIP') then
3217       -- This is a relationship party.  Get the person_party
3218       -- associated with this relationship as the party_id
3219       begin
3220         l_cust_person_party_id :=
3221           FND_OAM_USER_INFO.GET_ORGANIZATION_ID(l_customer_id);
3222       exception
3223         when no_data_found then
3224           if (log_exception = 'Y') then
3225             fnd_message.set_name('FND', 'USER_INVALID_PARTY_REL');
3226             fnd_message.set_token('USER', user_name);
3227             fnd_message.set_token('PNAME', l_party_name);
3228             fnd_message.set_token('CUSTID', l_customer_id);
3229             if (fnd_log.LEVEL_EXCEPTION >= fnd_log.g_current_runtime_level) then
3230               fnd_log.message(FND_LOG.LEVEL_EXCEPTION,
3231               c_log_head || l_api_name || '.not_in_hz_party_relationships',
3232               FALSE);
3233             end if;
3234             app_exception.raise_exception;
3235           else
3236             return null;
3237           end if;
3238       end;
3239     else
3240       if (log_exception = 'Y') then
3241         -- Invalid party type, raise error
3242         fnd_message.set_name('FND', 'USER_INVALID_PARTY_TYPE');
3243         fnd_message.set_token('USER', user_name);
3244         fnd_message.set_token('PNAME', l_party_name);
3245         fnd_message.set_token('PARTYID', l_customer_id);
3246         fnd_message.set_token('PARTY_TYPE', l_party_type);
3247         if (fnd_log.LEVEL_EXCEPTION >= fnd_log.g_current_runtime_level) then
3248           fnd_log.message(FND_LOG.LEVEL_EXCEPTION,
3249           c_log_head || l_api_name || '.bad_party_type', FALSE);
3250         end if;
3251         app_exception.raise_exception;
3252       else
3253         return null;
3254       end if;
3255     end if;
3256 
3257   end if;
3258 
3259   -- *** Derive party for employee_id ***
3260   if (l_employee_id is not NULL) then
3261         begin
3262      /*
3263        select party_id
3264        into l_emp_person_party_id
3265        from per_all_people_f
3266        where person_id = l_employee_id
3267        and trunc(sysdate) between effective_start_date
3268                           and effective_end_date;
3269      */
3270 
3271      -- Modified above SQL for bug 3094664
3272 
3273      l_emp_person_party_id := FND_OAM_USER_INFO.GET_PARTY_ID(l_employee_id);
3274     exception
3275       when no_data_found then
3276         if (log_exception = 'Y') then
3277           fnd_message.set_name('FND', 'USER_INVALID_EMPLOYEE');
3278           fnd_message.set_token('USER', user_name);
3279           fnd_message.set_token('EMPID', l_employee_id);
3280           if (fnd_log.LEVEL_EXCEPTION >= fnd_log.g_current_runtime_level) then
3281             fnd_log.message(FND_LOG.LEVEL_EXCEPTION,
3282             c_log_head || l_api_name || '.bad_empid', FALSE);
3283           end if;
3284           app_exception.raise_exception;
3285         else
3286           return null;
3287         end if;
3288     end;
3289   end if;
3290 
3291   -- Get person_party_id from customer or employee version
3292   if (l_cust_person_party_id is not null) then
3293     if (l_emp_person_party_id is not null) then
3294       -- Both found, check for mismatch
3295       if (l_cust_person_party_id <> l_emp_person_party_id) then
3296         if (log_exception = 'Y') then
3297           begin
3298           FND_OAM_USER_INFO.HZ_PARTY_ID_TO_NAME(l_cust_person_party_id,
3299                                                 l_cust_person_party_name,
3300                                                 l_party_type);
3301           exception
3302             when no_data_found then
3303               fnd_message.set_name('FND', 'USER_CUST_PARTY_NOT_FOUND');
3304               fnd_message.set_token('USER', user_name);
3305               fnd_message.set_token('CUSTID', l_customer_id);
3306               if (fnd_log.LEVEL_EXCEPTION >=
3307                                  fnd_log.g_current_runtime_level) then
3308                 fnd_log.message(FND_LOG.LEVEL_EXCEPTION,
3309                 c_log_head || l_api_name || '.cust_emp_mismatch', FALSE);
3310               end if;
3311               app_exception.raise_exception;
3312           end;
3313 
3314           begin
3315           FND_OAM_USER_INFO.HZ_PARTY_ID_TO_NAME(l_emp_person_party_id,
3316                                                 l_emp_person_party_name,
3317                                                 l_party_type);
3318           exception
3319             when no_data_found then
3320               fnd_message.set_name('FND', 'USER_EMP_PARTY_NOT_FOUND');
3321               fnd_message.set_token('USER', user_name);
3322               fnd_message.set_token('EMPID', l_emp_person_party_id);
3323               if (fnd_log.LEVEL_EXCEPTION >=
3324                                  fnd_log.g_current_runtime_level) then
3325                 fnd_log.message(FND_LOG.LEVEL_EXCEPTION,
3326                 c_log_head || l_api_name || '.cust_emp_mismatch', FALSE);
3327               end if;
3328               app_exception.raise_exception;
3329           end;
3330 
3331           fnd_message.set_name('FND', 'USER_CUST_EMP_MISMATCH');
3332           fnd_message.set_token('USER', user_name);
3333           fnd_message.set_token('CUSTID', l_customer_id);
3334           fnd_message.set_token('CUSTPARTY', l_cust_person_party_name);
3335           fnd_message.set_token('EMPID', l_employee_id);
3336           fnd_message.set_token('EMPPARTY', l_emp_person_party_name);
3337           if (fnd_log.LEVEL_EXCEPTION >= fnd_log.g_current_runtime_level) then
3338             fnd_log.message(FND_LOG.LEVEL_EXCEPTION,
3339             c_log_head || l_api_name || '.cust_emp_mismatch', FALSE);
3340           end if;
3341           app_exception.raise_exception;
3342         else
3343           return null;
3344         end if;
3345       end if;
3346     end if;
3347     -- Either no empid, or a matching one, use customer version
3348     z_person_party_id := l_cust_person_party_id;
3349   else
3350     -- Use employee version
3351     z_person_party_id := l_emp_person_party_id;
3352   end if;
3353 
3354   -- Save away keys in cache and return
3355   z_customer_id := customer_id;
3356   z_employee_id := employee_id;
3357   return(z_person_party_id);
3358 end DERIVE_PERSON_PARTY_ID;
3359 
3360 ----------------------------------------------------------------------
3361 --
3362 -- DERIVE_CUSTOMER_EMPLOYEE_ID
3363 --   Update customer and employee ids if person_party_id is changed
3364 -- IN
3365 --   user_name - User name (used for error messages)
3366 --   person_party_id - Party id
3367 -- OUT
3368 --   customer_id - Derived customer id
3369 --   employee_id - Derived employee id
3370 --
3371 Procedure DERIVE_CUSTOMER_EMPLOYEE_ID(
3372   user_name in varchar2,
3373   person_party_id in number,
3374   customer_id out nocopy number,
3375   employee_id out nocopy number)
3376 is
3377   l_api_name CONSTANT VARCHAR2(30) := 'DERIVE_CUSTOMER_EMPLOYEE_ID';
3378   l_person_party_id number;
3379   l_employee_id number;
3380   l_customer_id number;
3381   l_person_party_name varchar2(360);
3382   l_party_type varchar2(30);
3383   l_cursorid integer;
3384   l_blockstr varchar2(1000);
3385   l_dummy integer;
3386   l_party_id number;
3387   l_person_id number(30);
3388   l_matches varchar2(1);
3389 
3390 begin
3391   l_person_party_id := person_party_id;
3392 
3393   -- if we have the value cached, just return the cached value.
3394   if (    (   (z_rev_person_party_id = l_person_party_id)
3395            or (z_rev_person_party_id is NULL and l_person_party_id is NULL)))
3396     then
3397        customer_id := z_rev_customer_id;
3398        employee_id := z_rev_employee_id;
3399        return;
3400   end if;
3401 
3402   -- Validate person_party_id is correct type
3403   if (l_person_party_id is not null) then
3404     begin
3405       FND_OAM_USER_INFO.HZ_PARTY_ID_TO_NAME(l_person_party_id,
3406                                             l_person_party_name,
3407                                             l_party_type);
3408     exception
3409       when no_data_found then
3410         fnd_message.set_name('FND', 'USER_INVALID_PARTY');
3411         fnd_message.set_token('USER', user_name);
3412         fnd_message.set_token('PARTYID', l_person_party_id);
3413         if (fnd_log.LEVEL_EXCEPTION >= fnd_log.g_current_runtime_level) then
3414           fnd_log.message(FND_LOG.LEVEL_EXCEPTION,
3415             c_log_head || l_api_name || '.not_in_hz_parties', FALSE);
3416         end if;
3417         app_exception.raise_exception;
3418     end;
3419     if (l_party_type <> 'PERSON') then
3420       fnd_message.set_name('FND', 'USER_INVALID_PARTY_TYPE');
3421       fnd_message.set_token('USER', user_name);
3422       fnd_message.set_token('PARTYID', l_person_party_id);
3423       fnd_message.set_token('PARTY_TYPE', l_party_type);
3424       if (fnd_log.LEVEL_EXCEPTION >= fnd_log.g_current_runtime_level) then
3425         fnd_log.message(FND_LOG.LEVEL_EXCEPTION,
3426         c_log_head || l_api_name || '.bad_party_type', FALSE);
3427       end if;
3428       app_exception.raise_exception;
3429     end if;
3430   end if;
3431 
3432   -- Set customer_id to new party_id
3433   l_customer_id := l_person_party_id;
3434 
3435   -- Fix for Bug#3776819 - Derive employee id
3436   -- Use Dynamic SQL to execute the HR API to derive the person id
3437   begin
3438     l_cursorid := dbms_sql.open_cursor;
3439     l_blockstr :=
3440               'BEGIN
3441                 hr_tca_utility.get_person_id(p_party_id => :l_party_id, p_person_id => :l_person_id, p_matches => :l_matches);
3442               END;';
3443 
3444      dbms_sql.parse(l_cursorid, l_blockstr, dbms_sql.v7);
3445 
3446      dbms_sql.bind_variable(l_cursorid, ':l_party_id', l_person_party_id);
3447      dbms_sql.bind_variable(l_cursorid, ':l_person_id', l_person_id);
3448      dbms_sql.bind_variable(l_cursorid, ':l_matches', l_matches, 1);
3449 
3450      l_dummy := dbms_sql.execute(l_cursorid);
3451 
3452      dbms_sql.variable_value(l_cursorid, ':l_person_id', l_person_id);
3453      dbms_sql.variable_value(l_cursorid, ':l_matches', l_matches);
3454      dbms_sql.close_cursor(l_cursorid);
3455 
3456      -- Set the employee id
3457      if (l_person_id is not null) then
3458         l_employee_id := l_person_id;
3459      else
3460         -- Clear the employee_id
3461         l_employee_id := null;
3462      end if;
3463 
3464     -- Clear the employee_id
3465     --l_employee_id := null;
3466 
3467   exception
3468       when others then
3469         l_employee_id := null;
3470         dbms_sql.close_cursor(l_cursorid);
3471   end;
3472 
3473     -- Return
3474     customer_id := l_customer_id;
3475     employee_id := l_employee_id;
3476 
3477      -- Cache my new values
3478     z_rev_person_party_id := l_person_party_id;
3479     z_rev_customer_id := l_customer_id;
3480     z_rev_employee_id := l_employee_id;
3481 
3482 end DERIVE_CUSTOMER_EMPLOYEE_ID;
3483 
3484 ----------------------------------------------------------------------------
3485 --
3486 -- EnableUser (PUBLIC)
3487 --   Sets the start_date and end_date as requested. By default, the
3488 --   start_date will be set to sysdate and end_date to null.
3489 --   This is to enable that user.
3490 --   You can log in as this user from now.
3491 --   If username is not valid, exception raised with error message.
3492 --
3493 -- Usage example in pl/sql
3494 --   begin fnd_user_pkg.enableuser('SCOTT'); end;
3495 --   begin fnd_user_pkg.enableuser('SCOTT', sysdate+1, sysdate+30); end;
3496 --
3497 -- Input (Mandatory)
3498 --  username:       User Name
3499 -- Input (Non-Mandatory)
3500 --  start_date:     Start Date
3501 --  end_date:       End Date
3502 --
3503 procedure EnableUser(username varchar2,
3504                      start_date date default sysdate,
3505                      end_date date default fnd_user_pkg.null_date)  is
3506 begin
3507   fnd_user_pkg.UpdateUser(x_user_name => EnableUser.username,
3508                           x_owner => NULL,
3509                           x_start_date => EnableUser.start_date,
3510                           x_end_date  => EnableUser.end_date);
3511 end EnableUser;
3512 
3513 
3514 ----------------------------------------------------------------------------
3515 --
3516 -- CreatePendingUser (PUBLIC)
3517 --   Create a user whose start_date and end_date = FND_API.G_MISS_DATE as
3518 --   a pending user.
3519 --   Pending user is created when a user registers a user account through
3520 --   UMX with an aproval process.
3521 --
3522 --
3523 -- Usage example in pl/sql
3524 --   begin fnd_user_pkg.creatependinguser('SCOTT', 'SEED', 'welcome'); end;
3525 --   begin fnd_user_pkg.creatependinguser('SCOTT', 'SEED'); end;
3526 --
3527 -- Input (Mandatory)
3528 --  x_user_name:             User Name
3529 --  x_owner:                 'SEED' or 'CUST'(customer)
3530 --
3531 function CreatePendingUser(
3532   x_user_name                  in varchar2,
3533   x_owner                      in varchar2,
3534   x_unencrypted_password       in varchar2 default null,
3535   x_session_number             in number default 0,
3536   x_description                in varchar2 default null,
3537   x_password_date              in date default null,
3538   x_password_accesses_left     in number default null,
3539   x_password_lifespan_accesses in number default null,
3540   x_password_lifespan_days     in number default null,
3541   x_email_address              in varchar2 default null,
3542   x_fax                        in varchar2 default null,
3543   x_person_party_id            in number default null)  return number
3544 is
3545   uid number;
3546 begin
3547   uid := fnd_user_pkg.CreateUserIdParty(
3548     x_user_name,
3549     x_owner,
3550     x_unencrypted_password,
3551     x_session_number,
3552     FND_API.G_MISS_DATE,
3553     FND_API.G_MISS_DATE,
3554     null,
3555     x_description,
3556     x_password_date,
3557     x_password_accesses_left,
3558     x_password_lifespan_accesses,
3559     x_password_lifespan_days,
3560     x_email_address,
3561     x_fax,
3562     x_person_party_id);
3563   return(uid);
3564 
3565 
3566 end CreatePendingUser;
3567 
3568 
3569 ----------------------------------------------------------------------------
3570 --
3571 -- RemovePendingUser (PUBLIC)
3572 --   Delete this user from fnd_user table only if this is a pending user.
3573 --   If this is not a valid username or is not a pending user, raise error.
3574 --   Pending user is created when a user registers a user account through
3575 --   UMX with an aproval process.
3576 --
3577 -- Usage example in pl/sql
3578 --   begin fnd_user_pkg.removependinguser('SCOTT'); end;
3579 --
3580 -- Input (Mandatory)
3581 --  username:       User Name
3582 --
3583 procedure RemovePendingUser(username varchar2) is
3584   l_user_id number;
3585   retval pls_integer;
3586   l_user_guid raw(16);
3587 
3588   l_api_name varchar2(30) := 'REMOVEPENDINGUSER';
3589 begin
3590 
3591    if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
3592       fnd_log.string(FND_LOG.LEVEL_STATEMENT, C_LOG_HEAD || l_api_name,
3593                    'Begin');
3594    end if;
3595 
3596    -- Added for Function Security Cache Invalidation
3597    -- RSHEH: Need to have exception trapping for no_data_found exception
3598    begin
3599    select user_id, user_guid
3600    into l_user_id, l_user_guid
3601    from fnd_user
3602    where user_name = upper(username)
3603    and to_char(start_date) = to_char(FND_API.G_MISS_DATE)
3604    and to_char(end_date) = to_char(FND_API.G_MISS_DATE);
3605 
3606    exception
3607      when no_data_found then
3608 
3609       if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
3610           fnd_log.string(FND_LOG.LEVEL_STATEMENT, C_LOG_HEAD || l_api_name,
3611                    'No disabled user');
3612        end if;
3613 
3614      fnd_message.set_name('FND', 'FND_INVALID_USER');
3615      fnd_message.set_token('USER_NAME', username);
3616      app_exception.raise_exception;
3617    end;
3618 
3619   -- Bug 4318754. Synch up with SSO
3620   if (l_user_guid is not null) then
3621     begin
3622       if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
3623          fnd_log.string(FND_LOG.LEVEL_STATEMENT, C_LOG_HEAD || l_api_name,
3624                    'User guid is not null...call fnd_ldap_wrapper.delete_user');
3625       end if;
3626 
3627       fnd_ldap_wrapper.delete_user(l_user_guid, retval);
3628     if (retval <> fnd_ldap_wrapper.G_SUCCESS) then
3629         app_exception.raise_exception;
3630     end if;
3631     exception
3632       when others then
3633         app_exception.raise_exception;
3634     end;
3635   end if;
3636 
3637    -- Only allow to delete a PENDING user
3638    if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
3639        fnd_log.string(FND_LOG.LEVEL_STATEMENT, C_LOG_HEAD || l_api_name,
3640                    'Delete pending FND user');
3641     end if;
3642 
3643    delete from fnd_user
3644    where user_name = upper(username)
3645    and to_char(start_date) = to_char(FND_API.G_MISS_DATE)
3646    and to_char(end_date) = to_char(FND_API.G_MISS_DATE);
3647 
3648    if (sql%rowcount = 0) then
3649      if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
3650          fnd_log.string(FND_LOG.LEVEL_STATEMENT, C_LOG_HEAD || l_api_name,
3651                    'This pending user does not exist');
3652      end if;
3653      fnd_message.set_name('FND', 'FND_INVALID_USER');
3654      fnd_message.set_token('USER_NAME', username);
3655      app_exception.raise_exception;
3656    else
3657 
3658     -- Added for Function Security Cache Invalidation
3659     fnd_function_security_cache.delete_user(l_user_id);
3660 
3661    -- Bug 13824550
3662    -- A pending user was deleted...now need to remove this user from the WF
3663    -- tables by raising this event.
3664     if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
3665         fnd_log.string(FND_LOG.LEVEL_STATEMENT, C_LOG_HEAD || l_api_name,
3666                    'Call wf_directory.deleteRole to remove any inactive WF data associated with this user');
3667      end if;
3668 
3669      wf_directory.deleteRole(username,'FND_USR',l_user_id);
3670    end if;
3671 
3672      if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
3673         fnd_log.string(FND_LOG.LEVEL_STATEMENT, C_LOG_HEAD || l_api_name, 'End');
3674      end if;
3675 
3676 
3677 end RemovePendingUser;
3678 
3679 ----------------------------------------------------------------------------
3680 --
3681 -- AssignPartyToUser (PUBLIC)
3682 --   Assign a TCA party to a given user
3683 --
3684 -- Usage example in pl/sql
3685 --   begin fnd_user_pkg.assignpartytouser('SCOTT', 1001); end;
3686 --
3687 -- Input (Mandatory)
3688 --  x_user_name:       User Name
3689 --  x_party_id:        Party Name Id
3690 --
3691 procedure AssignPartyToUser(
3692   x_user_name                  in varchar2,
3693   x_party_id                   in number) is
3694 pid number;
3695 begin
3696 
3697 --07/03/03: party_name in table hz_parties is not unique. Therefore, change
3698 --the API to take party_id instead of party_name.
3699 /*
3700  -- Get party id
3701   begin
3702     select party_id
3703     into pid
3704     from hz_parties
3705     where upper(party_name) = upper(x_party);
3706   exception
3707     when no_data_found then
3708     fnd_message.set_name('FND', 'FND_INVALID_PARTY');
3709     fnd_message.set_token('PARTY_NAME', x_party);
3710     app_exception.raise_exception;
3711   end;
3712 
3713   fnd_user_pkg.UpdateUserParty(x_user_name => x_user_name,
3714                                x_owner => 'SEED',
3715                                x_person_party_id => pid);
3716 */
3717 
3718   fnd_user_pkg.UpdateUserParty(x_user_name => x_user_name,
3719                                x_owner => 'SEED',
3720                                x_person_party_id => x_party_id);
3721 
3722 end AssignPartyToUser;
3723 
3724 -- Internal. Called by change_user_name and the two parameters
3725 -- ldap_wrapper_change_user_name.
3726 procedure ldap_wrapper_change_user_name(x_user_guid in raw,
3727                                         x_old_user_name in varchar2,
3728                                         x_new_user_name in varchar2) is
3729 
3730   l_result number;
3731   reason varchar2(2000);
3732 begin
3733 
3734   l_result := null;
3735 
3736   fnd_ldap_wrapper.change_user_name(x_user_guid, x_old_user_name,
3737                                     x_new_user_name, l_result);
3738   if (l_result <> fnd_ldap_wrapper.G_SUCCESS) then
3739     reason := fnd_message.get();
3740     fnd_message.set_name('FND', 'LDAP_WRAPPER_CHANGE_USER_FAIL');
3741     fnd_message.set_token('REASON', reason);
3742       app_exception.raise_exception;
3743   end if;
3744 exception
3745   when others then
3746     fnd_message.set_name('FND', 'LDAP_WRAPPER_CHANGE_USER_FAIL');
3747     fnd_message.set_token('REASON', sqlerrm);
3748     app_exception.raise_exception;
3749 end;
3750 
3751 -- begin bug 2504562
3752 
3753 ----------------------------------------------------------------------------
3754 --
3755 -- change_user_name (PUBLIC)
3756 --   This api changes username, deals with encryption changes and
3757 --   update foreign keys that were using the old username.
3758 --
3759 -- Usage example in pl/sql
3760 --   begin fnd_user_pkg.change_user_name('SOCTT', 'SCOTT'); end;
3761 --
3762 -- Input (Mandantory)
3763 --   x_old_user_name:     Old User Name
3764 --   x_new_user_name:     New User Name
3765 --
3766 procedure change_user_name(x_old_user_name            in varchar2,
3767                            x_new_user_name            in varchar2,
3768                            x_change_source            in number default null) is
3769   newpass varchar2(100);
3770   dummy number(1);
3771   ret boolean;
3772   l_user_id number;
3773   l_user_guid raw(16);
3774   l_api_name  CONSTANT varchar2(30) := 'change_user_name';
3775   tmpbuf varchar2(240);
3776   reason varchar2(240);
3777   encpwd varchar2(100);
3778   l_parameter_list wf_parameter_list_t;  -- bug 8227171 WF event parameter list
3779 
3780 begin
3781   -- 7311525 do not allow the username of GUEST to be changed
3782   if (upper(x_old_user_name) = 'GUEST') then
3783      fnd_message.set_name('FND', 'SECURITY-GUEST USERNAME');
3784      app_exception.raise_exception;
3785   end if;
3786 
3787   -- ensure x_old_user_name exists in fnd_user before we proceed
3788   select USER_GUID, encrypted_user_password
3789   into l_user_guid, encpwd
3790   from fnd_user
3791   where user_name = upper(x_old_user_name);
3792 
3793   begin
3794     -- ensure x_new_user_name doesn't already exist in fnd_user
3795     select null into dummy from fnd_user
3796       where user_name = upper(x_new_user_name);
3797     fnd_message.set_name('FND', 'SECURITY-DUPLICATE USER');
3798     app_exception.raise_exception;
3799   exception
3800     when no_data_found then
3801       -- bug 8227171 change_user_name
3802       validate_user_name(x_new_user_name);
3803 
3804       -- Start bug 5866089 just adding the following if check
3805       if (x_change_source is null) then
3806 		-- Start bug 4625235
3807 		-- Move ldap_wrapper synch call to here before we do FND user update
3808 		begin
3809 		  tmpbuf := 'Calling ldap_wrapper_change_user_name to change '||
3810 					 x_old_user_name|| ' to '|| x_new_user_name;
3811 		  if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
3812 		  fnd_log.string(FND_LOG.LEVEL_STATEMENT, C_LOG_HEAD || l_api_name || '.',
3813 					 tmpbuf);
3814 		  end if;
3815 		  if (l_user_guid is not null) then
3816 		  ldap_wrapper_change_user_name(l_user_guid, upper(x_old_user_name),
3817 									  upper(x_new_user_name));
3818 		  end if;
3819 		exception
3820 		when others then
3821 		  app_exception.raise_exception;
3822 		end;
3823         -- end bug 4625235
3824 
3825       end if;
3826       -- end bug 5866089
3827 
3828       -- capture x_old_user_name in package variable g_old_user_name
3829       g_old_user_name := upper(x_old_user_name);
3830 
3831       -- change old username to new username
3832       update fnd_user set user_name = upper(x_new_user_name)
3833         where user_name = upper(x_old_user_name);
3834 
3835       -- This code was moved before updating FND_USER due to a change in
3836       -- FND_WEB_SEC.change_password having an autonomous transaction pragma.
3837       -- Password changes failed due to said change.  See bug 2426407.
3838       -- handle password encryption with new username
3839       tmpbuf := 'Recrypting '||x_new_user_name|| ' password';
3840       if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
3841       fnd_log.string(FND_LOG.LEVEL_STATEMENT, C_LOG_HEAD || l_api_name || '.',
3842                    tmpbuf);
3843       end if;
3844 
3845       -- Only have to do password reencryption if is not EXTERNAL, INVALID or Hash mode
3846       if ( (encpwd not in ('EXTERNAL', 'INVALID')) and (substr(encpwd, 1, 1) <> 'X') ) then
3847         newpass := fnd_user_pkg.GetReEncryptedPassword(x_new_user_name, 'NEWKEY');
3848         ret := fnd_user_pkg.SetReEncryptedPassword(x_new_user_name,newpass,'NEWKEY');
3849       end if;
3850 
3851       tmpbuf := 'updating fnd_user for new user_name '||x_new_user_name;
3852       if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
3853       fnd_log.string(FND_LOG.LEVEL_STATEMENT, C_LOG_HEAD || l_api_name || '.',
3854                    tmpbuf);
3855       end if;
3856 
3857       -- In the below WHERE clause, 'upper' is added, otherwise if the
3858       --  x_new_user_name contains any small case letters, it will enter into
3859       -- 'NO-DATA-FOUND' (since in the above statement, UPPER(x_new_user_name)
3860       --  is stored) exception and returns FND_CHANGE_USER_FAILED error.
3861       -- Added for Function Security Cache Invalidation
3862       select user_id
3863       into l_user_id
3864       from fnd_user
3865       where user_name = upper(x_new_user_name);
3866 
3867       fnd_function_security_cache.update_user(l_user_id);
3868 
3869       -- propagate username change to WF and entity mgr
3870       tmpbuf := 'Start calling fnd_user_pkg.user_synch('||x_new_user_name||')';
3871       if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
3872       fnd_log.string(FND_LOG.LEVEL_STATEMENT, C_LOG_HEAD || l_api_name || '.',
3873                    tmpbuf);
3874       end if;
3875       begin
3876       fnd_user_pkg.user_synch(upper(x_new_user_name));
3877       exception
3878         when others then
3879           reason := fnd_message.get;
3880           fnd_message.set_name('FND', 'FND_FAILED_WF_USER_SYNCH');
3881           fnd_message.set_token('OLD_NAME', x_old_user_name);
3882           fnd_message.set_token('NEW_NAME', x_new_user_name);
3883           fnd_message.set_token('REASON', reason);
3884           app_exception.raise_exception;
3885       end;
3886 
3887       -- Added for bug 4676568
3888       -- A temp fix to update fnd_grants.grantee_key
3889       -- No need to check SQL%NOTFOUND because if there is no data to be
3890       -- updated in fnd_grants.grantee_key, that is perfectly fine.
3891       update fnd_grants
3892       set grantee_key = x_new_user_name
3893       where grantee_key = x_old_user_name
3894       and grantee_type = 'USER';
3895 
3896       tmpbuf := 'Finished fnd_user_pkg.user_synch';
3897       if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
3898       fnd_log.string(FND_LOG.LEVEL_STATEMENT, C_LOG_HEAD || l_api_name || '.',
3899                    tmpbuf);
3900       end if;
3901 
3902       -- bug 8227171 change_user_name
3903       -- Raise the WF event oracle.apps.fnd.post.username.change
3904       begin
3905         wf_event.AddParameterToList('OLD_USERNAME', x_old_user_name,
3906 l_parameter_list);
3907         wf_event.raise3(p_event_name =>'oracle.apps.fnd.post.username.change',
3908                   p_event_key => x_new_user_name,
3909                   p_event_data => NULL,
3910                   p_parameter_list => l_parameter_list,
3911                   p_send_date => Sysdate);
3912 
3913       exception
3914          when others then
3915           reason := fnd_message.get_encoded;
3916           if (reason is not null) then
3917             fnd_message.set_encoded(reason);
3918           else
3919             fnd_message.set_name('FND', 'FND_RAISE_EVENT_FAILED');
3920           end if;
3921           app_exception.raise_exception;
3922       end;
3923   end;
3924 
3925 exception
3926   when no_data_found then
3927     -- old username does not exist in fnd_user
3928     fnd_message.set_name('FND', 'FND_CHANGE_USER_FAILED');
3929     fnd_message.set_token('USER_NAME', x_old_user_name);
3930     app_exception.raise_exception;
3931 
3932 
3933 end change_user_name;
3934 
3935 ----------------------------------------------------------------------------
3936 --
3937 -- set_old_user_name (PUBLIC)
3938 --   This function is called from Forms to set the global variable,
3939 --   g_old_user_name since this cannot be set directly from Forms.
3940 --   This function returns a number which can be used to check for success
3941 --   from Forms.
3942 --
3943 -- Usage example in pl/sql
3944 --   declare
3945 --     retval number := null;
3946 --   begin retval := fnd_user_pkg.set_old_user_name('SOCTT'); end;
3947 --
3948 -- Input (Mandantory)
3949 --   x_old_user_name:     Old User Name
3950 --
3951 function set_old_user_name(x_old_user_name in varchar2) return number is
3952   retval number := null;
3953 begin
3954   g_old_user_name := x_old_user_name;
3955   if (g_old_user_name is not null) then
3956         retval := 1;
3957   else
3958         retval := 0;
3959   end if;
3960   return retval;
3961 end;
3962 
3963 -- end bug 2504562
3964 
3965 ----------------------------------------------------------------------------
3966 -- MergePartyId (PUBLIC)
3967 --   This is the procedure being called during the Party Merge.
3968 --   FND_USER.MergePartyId() has been registered in Party Merge Data Dict.
3969 --   The input/output arguments format matches the document PartyMergeDD.doc.
3970 --   The goal is to fix the person_party_id in fnd_user table to point to the
3971 --   same party when two similar parties are begin merged.
3972 --
3973 -- Usage example in pl/sql
3974 --   This procedure should only be called from the PartyMerge utility.
3975 --
3976 procedure MergePartyId(p_entity_name in varchar2,
3977                        p_from_id in number,
3978                        p_to_id in out nocopy number,
3979                        p_from_fk_id in number,
3980                        p_to_fk_id in number,
3981                        p_parent_entity_name in varchar2,
3982                        p_batch_id in number,
3983                        p_batch_party_id in number,
3984                        p_return_status in out nocopy varchar2) is
3985 begin
3986   p_return_status := FND_API.G_RET_STS_SUCCESS;
3987 
3988   if (p_from_fk_id <> p_to_fk_id) then
3989 
3990     update fnd_user
3991     set person_party_id = p_to_fk_id
3992     where person_party_id = p_from_fk_id;
3993 
3994     -- Added for Function Security Cache Invalidation
3995     fnd_function_security_cache.update_user(p_from_id);
3996 
3997   end if;
3998 
3999 end MergePartyId;
4000 
4001 -- Public function
4002 -- Make sure that the user_name does not contain invalid character.
4003 -- For now: We only care about '/' and ':' because they are known problem.
4004 -- 01/19/05: we now have more invalid characters info from bug 4116239, so
4005 --           I am adding more characters.
4006 -- Rewrite later: checking for any non-printable character.
4007 --                make sure multibyte character is ok.
4008 procedure validate_user_name(x_user_name in varchar2) is
4009 msg varchar2(2000);
4010 uname varchar2(100);
4011 begin
4012   if (x_user_name is null or
4013       rtrim(x_user_name, ' ') is null) then
4014     fnd_message.set_name('FND', 'INVALID_USER_NAME_NULL');
4015     app_exception.raise_exception;
4016   elsif (rtrim(x_user_name, ' ') <> x_user_name or
4017          ltrim(x_user_name, ' ') <> x_user_name) then
4018     fnd_message.set_name('FND', 'INVALID_USER_NAME_SPACE');
4019     app_exception.raise_exception;
4020   elsif (instr(x_user_name, '/') > 0 OR
4021       instr(x_user_name, '"') > 0 OR
4022       instr(x_user_name, '(') > 0 OR
4023       instr(x_user_name, ')') > 0 OR
4024       instr(x_user_name, '*') > 0 OR
4025       instr(x_user_name, '+') > 0 OR
4026       instr(x_user_name, ',') > 0 OR
4027       instr(x_user_name, ';') > 0 OR
4028       instr(x_user_name, '<') > 0 OR
4029       instr(x_user_name, '>') > 0 OR
4030       instr(x_user_name, '\') > 0 OR
4031       instr(x_user_name, '~') > 0 OR
4032       instr(x_user_name, ':') > 0 ) then
4033     fnd_message.set_name('FND', 'INVALID_USER_NAME');
4034     fnd_message.set_token('UNAME', x_user_name);
4035     app_exception.raise_exception;
4036   else
4037     -- we pass the generic validation, it is time to call any
4038     -- customized user name validation if there is any.
4039     begin
4040       wf_event.raise(p_event_name => 'oracle.apps.fnd.user.name.validate',
4041                      p_event_key => x_user_name,
4042                      p_event_data => NULL,
4043                      p_parameters => NULL,
4044                      p_send_date => Sysdate);
4045     exception
4046       when others then
4047         msg := fnd_message.get_encoded;
4048         if (msg is not null) then
4049           fnd_message.set_encoded(msg);
4050         else
4051           fnd_message.set_name('FND', 'FND_CUST_UNAME_VALIDATE_FAILED');
4052         end if;
4053         app_exception.raise_exception;
4054     end;
4055     -- past generic and customized validation
4056   end if;
4057 
4058 end validate_user_name;
4059 
4060 --
4061 -- CreateUser (PUBLIC)
4062 --
4063 --   Bug#3904339 - SSO: Add user_guid parameter in fnd_user_pkg apis
4064 --   Overloaded procedure to create user
4065 --   Accepts  User GUID as a parameter in addition to the other parameters
4066 --
4067 --
4068 procedure CreateUser (
4069   x_user_name                  in varchar2,
4070   x_owner                      in varchar2,
4071   x_unencrypted_password       in varchar2 default null,
4072   x_session_number             in number default 0,
4073   x_start_date                 in date default sysdate,
4074   x_end_date                   in date default null,
4075   x_last_logon_date            in date default null,
4076   x_description                in varchar2 default null,
4077   x_password_date              in date default null,
4078   x_password_accesses_left     in number default null,
4079   x_password_lifespan_accesses in number default null,
4080   x_password_lifespan_days     in number default null,
4081   x_employee_id                in number default null,
4082   x_email_address              in varchar2 default null,
4083   x_fax                        in varchar2 default null,
4084   x_customer_id                in number default null,
4085   x_supplier_id                in number default null,
4086   x_user_guid                  in raw,
4087   x_change_source              in number default null)
4088 is
4089   l_result number;
4090 begin
4091   l_result := fnd_user_pkg.CreateUserId(
4092     x_user_name,
4093     x_owner,
4094     x_unencrypted_password,
4095     x_session_number,
4096     x_start_date,
4097     x_end_date,
4098     x_last_logon_date,
4099     x_description,
4100     x_password_date,
4101     x_password_accesses_left,
4102     x_password_lifespan_accesses,
4103     x_password_lifespan_days,
4104     x_employee_id,
4105     x_email_address,
4106     x_fax,
4107     x_customer_id,
4108     x_supplier_id,
4109     x_user_guid,
4110     x_change_source);
4111 end CreateUser;
4112 
4113 ----------------------------------------------------------------------
4114 --
4115 -- CreateUserId (PUBLIC)
4116 --
4117 --   Bug#3904339 - SSO: Add user_guid parameter in fnd_user_pkg apis
4118 --   Overloaded procedure to create user
4119 --   Accepts  User GUID as a parameter in addition to the other parameters
4120 --
4121 -- Returns
4122 --   User_id of created user
4123 --
4124 
4125 function CreateUserId (
4126   x_user_name                  in varchar2,
4127   x_owner                      in varchar2,
4128   x_unencrypted_password       in varchar2 default null,
4129   x_session_number             in number default 0,
4130   x_start_date                 in date default sysdate,
4131   x_end_date                   in date default null,
4132   x_last_logon_date            in date default null,
4133   x_description                in varchar2 default null,
4134   x_password_date              in date default null,
4135   x_password_accesses_left     in number default null,
4136   x_password_lifespan_accesses in number default null,
4137   x_password_lifespan_days     in number default null,
4138   x_employee_id                in number default null,
4139   x_email_address              in varchar2 default null,
4140   x_fax                        in varchar2 default null,
4141   x_customer_id                in number default null,
4142   x_supplier_id                in number default null,
4143   x_user_guid                  in raw,
4144   x_change_source              in number default null)
4145 return number is
4146 begin
4147   return CreateUserIdInternal(
4148     x_user_name => x_user_name,
4149     x_owner => x_owner,
4150     x_unencrypted_password => x_unencrypted_password,
4151     x_session_number => x_session_number,
4152     x_start_date => x_start_date,
4153     x_end_date => x_end_date,
4154     x_last_logon_date => x_last_logon_date,
4155     x_description => x_description,
4156     x_password_date => x_password_date,
4157     x_password_accesses_left => x_password_accesses_left,
4158     x_password_lifespan_accesses => x_password_lifespan_accesses,
4159     x_password_lifespan_days => x_password_lifespan_days,
4160     x_employee_id => x_employee_id,
4161     x_email_address => x_email_address,
4162     x_fax => x_fax,
4163     x_customer_id => x_customer_id,
4164     x_supplier_id => x_supplier_id,
4165     x_person_party_id => null,
4166     x_mode => 'EMPLOYEE',
4167     x_user_guid => x_user_guid,
4168     x_change_source => x_change_source);
4169 end CreateUserId;
4170 
4171 ----------------------------------------------------------------------
4172 --
4173 -- UpdateUser (Public)
4174 --
4175 --   Bug#3904339 - SSO: Add user_guid parameter in fnd_user_pkg apis
4176 --   Overloaded procedure to update user
4177 --   Accepts  User GUID as a parameter in addition to the other parameters
4178 --
4179 procedure UpdateUser (
4180   x_user_name                  in varchar2,
4181   x_owner                      in varchar2,
4182   x_unencrypted_password       in varchar2 default null,
4183   x_session_number             in number default null,
4184   x_start_date                 in date default null,
4185   x_end_date                   in date default null,
4186   x_last_logon_date            in date default null,
4187   x_description                in varchar2 default null,
4188   x_password_date              in date default null,
4189   x_password_accesses_left     in number default null,
4190   x_password_lifespan_accesses in number default null,
4191   x_password_lifespan_days     in number default null,
4192   x_employee_id                in number default null,
4193   x_email_address              in varchar2 default null,
4194   x_fax                        in varchar2 default null,
4195   x_customer_id                in number default null,
4196   x_supplier_id                in number default null,
4197   x_old_password               in varchar2 default null,
4198   x_user_guid                  in raw,
4199   x_change_source              in number default null)
4200 is
4201 begin
4202   UpdateUserInternal(
4203     x_user_name => x_user_name,
4204     x_owner => x_owner,
4205     x_unencrypted_password => x_unencrypted_password,
4206     x_session_number => x_session_number,
4207     x_start_date => x_start_date,
4208     x_end_date => x_end_date,
4209     x_last_logon_date => x_last_logon_date,
4210     x_description => x_description,
4211     x_password_date => x_password_date,
4212     x_password_accesses_left => x_password_accesses_left,
4213     x_password_lifespan_accesses => x_password_lifespan_accesses,
4214     x_password_lifespan_days => x_password_lifespan_days,
4215     x_employee_id => x_employee_id,
4216     x_email_address => x_email_address,
4217     x_fax => x_fax,
4218     x_customer_id => x_customer_id,
4219     x_supplier_id => x_supplier_id,
4220     x_person_party_id => null,
4221     x_old_password => x_old_password,
4222     x_mode => 'EMPLOYEE',
4223     x_user_guid => x_user_guid,
4224     x_change_source => x_change_source);
4225 end UpdateUser;
4226 
4227 ----------------------------------------------------------------------
4228 -- userExists (Public)
4229 --
4230 -- This function checks if the user exists and returnes 'True' or 'False'
4231 -- Input (Mandatory)
4232 --  username: User Name
4233 
4234 function userExists(x_user_name in varchar2) return boolean is
4235  dummy number;
4236 begin
4237  select 1 into dummy from fnd_user
4238  where user_name = upper(x_user_name);
4239  return TRUE;
4240 exception
4241  when no_data_found then
4242  return FALSE;
4243 end userExists;
4244 
4245 -- begin bug 4318754, 4424225
4246 ----------------------------------------------------------------------------
4247 --
4248 -- TestUserName (PUBLIC)
4249 --   This api test whether a username exists in FND and/or in OID.
4250 --
4251 -- Usage example in pl/sql
4252 --   declare ret number;
4253 --   begin ret := fnd_user_pkg.testusername('SOCTT'); end;
4254 --
4255 -- Input (Mandantory)
4256 --   x_user_name:     User Name that you want to test
4257 --
4258 -- Output
4259 --   USER_INVALID_NAME : User name is not valid
4260 --   USER_OK_CREATE : User does not exist in either FND or OID
4261 --   USER_EXISTS_IN_FND : User exists in FND
4262 --   USER_SYNCH : User exists in OID and next time when this user gets created
4263 --                in FND, the two will be synched together.
4264 --   USER_EXISTS_NO_LINK_ALLOWED: User exists in OID and no synching allowed.
4265 --
4266 function TestUserName(x_user_name in varchar2) return pls_integer is
4267   pf varchar2(1);
4268   retval pls_integer;
4269 begin
4270 
4271   pf := 'N';
4272 
4273   begin
4274     fnd_user_pkg.validate_user_name(x_user_name);
4275   exception
4276     when others then
4277     -- error message is already on the stack from validate_user_name()
4278     -- Either a generic validation error message or specific message from
4279     -- the subscriber of "fnd.user.name.validate"
4280     return(USER_INVALID_NAME);
4281   end;
4282 
4283   if (fnd_user_pkg.userExists(x_user_name)) then
4284     fnd_message.set_name('FND', 'FND_USER_EXISTS_IN_FND');
4285     return(USER_EXISTS_IN_FND);
4286   else
4287     begin
4288        retval := fnd_ldap_wrapper.user_exists(x_user_name);
4289     exception
4290       when others then
4291         app_exception.raise_exception;
4292     end;
4293 
4294     if (retval = 1) then
4295       -- The above check return that user exists in oid.
4296       fnd_profile.get('APPS_SSO_LINK_SAME_NAMES', pf);
4297 
4298       if(pf = 'Y') then
4299         fnd_message.set_name('FND', 'FND_USER_SYNCHED');
4300         fnd_message.set_token('USER_NAME', x_user_name);
4301         return(USER_SYNCHED);
4302         -- next time when this user gets created in fnd, it will be
4303         -- linked to each other.
4304       else
4305         fnd_message.set_name('FND', 'FND_USER_EXISTS_NO_LINK');
4306         return(USER_EXISTS_NO_LINK_ALLOWED);
4307       end if;
4308     else
4309       return(USER_OK_CREATE);
4310     end if;
4311   end if;
4312 
4313 end TestUserName;
4314 
4315 
4316 ----------------------------------------------------------------------------
4317 --
4318 -- set_old_person_party_id (PUBLIC)
4319 --   This function is called from Forms to set the global variable,
4320 --   g_old_person_party_id since this cannot be set directly from Forms.
4321 --   This function returns a number which can be used to check for success
4322 --   from Forms.
4323 --
4324 -- Usage example in pl/sql
4325 --   declare
4326 --     retval number := null;
4327 --   begin retval := fnd_user_pkg.set_old_person_party_id(12345); end;
4328 --
4329 -- Input (Mandantory)
4330 --   x_old_person_party_id:     Old Person Party Id
4331 --
4332 function set_old_person_party_id(x_old_person_party_id in varchar2)
4333 return number is
4334   retval number := null;
4335 begin
4336   g_old_person_party_id := x_old_person_party_id;
4337   if (g_old_person_party_id is not null) then
4338         retval := 1;
4339   else
4340         retval := 0;
4341   end if;
4342   return retval;
4343 end;
4344 
4345 
4346 ----------------------------------------------------------------------------
4347 --
4348 -- set_old_user_guid (PUBLIC)
4349 --   This function is called from Forms to set the global variable,
4350 --   g_old_user_guid since this cannot be set directly from Forms.
4351 --   This function returns a number which can be used to check for success
4352 --   from Forms.
4353 --
4354 -- Usage example in pl/sql
4355 --   declare
4356 --     retval number := null;
4357 --     guid raw(16);
4358 --   begin
4359 --     guid := 'F9374D4B80AB1A86E034080020B2612C';
4360 --     retval := fnd_user_pkg.set_old_user_guid(guid); end;
4361 --
4362 -- Input (Mandantory)
4363 --   x_old_user_guid:     Old USER GUID
4364 --
4365 function set_old_user_guid(x_old_user_guid in raw)
4366 return number is
4367   retval number := null;
4368 begin
4369   g_old_user_guid := x_old_user_guid;
4370   if (g_old_person_party_id is not null) then
4371         retval := 1;
4372   else
4373         retval := 0;
4374   end if;
4375   return retval;
4376 end;
4377 
4378 -- Internal
4379 function ldap_wrp_update_user_helper(x_user_name in varchar2,
4380                                    x_unencrypted_password in varchar2,
4381                                    x_start_date in date,
4382                                    x_end_date in date,
4383                                    x_description in varchar2,
4384                                    x_email_address in varchar2,
4385                                    x_fax in varchar2,
4386                                    x_expire_pwd in pls_integer) return varchar2
4387 is
4388     l_user_guid raw(16);
4389     l_result number;
4390     reason varchar2(2000);
4391     l_pwd varchar2(1000);
4392     pwdCaseOpt varchar2(1);
4393     l_pwd_ret varchar2(1000);
4394     userid number; -- bug 5162136
4395     isOverrideFuncAssigned	boolean; /* 7043484 */
4396     l_api_name varchar2(80) := 'ldap_wrp_update_user_helper';
4397 begin
4398 
4399   l_user_guid := null;
4400   l_result := null;
4401   l_pwd_ret := null;
4402   userid := null;
4403 
4404   if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
4405          fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
4406                      'Begin');
4407   end if;
4408 
4409 
4410   -- bug 5162136 Obtain the user_id for later use
4411   select user_guid, user_id into l_user_guid, userid
4412   from fnd_user
4413   where user_name = x_user_name;
4414 
4415   if (l_user_guid is null) then
4416      if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
4417          fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
4418                      'Not a SSO user - no user_guid found');
4419      end if;
4420     return null;
4421   end if;
4422 
4423   -- Only check the profile and expiration if password is not null
4424   l_pwd := x_unencrypted_password;
4425   if (x_unencrypted_password is not null) then
4426     if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
4427          fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
4428                      'Password is not null' );
4429      end if;
4430     -- Bug 5161497
4431     -- If profile is not set or case insensitive, then password passed to
4432     -- sso/oid should be lower. This has been discussed with SSO to
4433     -- reach agreement because entering lower case is more common for case
4434     -- insensitive mode.
4435     pwdCaseOpt := null;
4436     -- 5162136 SIGNON_PASSWORD_CASE Profile Check
4437     -- Get the profile value at the user level for the affected user and
4438     -- encrypt accordingly.  If not set at the user level, this will default to
4439     -- the site level profile value.
4440     /* Code change for bug 7043484 */
4441     isOverrideFuncAssigned := fnd_function.test('OVERRIDE_PASSWORD_POLICY_PERM','N');
4442     if(isOverrideFuncAssigned = true) then
4443       pwdCaseOpt := fnd_profile.value('SIGNON_PASSWORD_CASE');
4444 	else
4445 	  pwdCaseOpt := fnd_profile.value_specific('SIGNON_PASSWORD_CASE', userid);
4446 	end if;
4447     if (pwdCaseOpt is null) or (pwdCaseOpt = '1') then
4448       l_pwd := lower(x_unencrypted_password);
4449     end if;
4450   end if; -- End if x_unencrypted_password is not null
4451 
4452   begin
4453 
4454     if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
4455          fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head || l_api_name,
4456                      'Now call to fnd_ldap_wrapper.update_user');
4457      end if;
4458 
4459     fnd_ldap_wrapper.update_user(l_user_guid, x_user_name,
4460           l_pwd, x_start_date, x_end_date, x_description,
4461           x_email_address, x_fax, x_expire_pwd, l_pwd_ret, l_result);
4462 
4463     if (l_result <> fnd_ldap_wrapper.G_SUCCESS) then
4464       reason := fnd_message.get();
4465       fnd_message.set_name('FND', 'LDAP_WRAPPER_UPDATE_USER_FAIL');
4466       fnd_message.set_token('USER_NAME', x_user_name);
4467       fnd_message.set_token('REASON', reason);
4468       app_exception.raise_exception;
4469     -- Bug 5605892
4470     end if;
4471 
4472     -- Bug 5605892
4473     if (l_pwd_ret = fnd_web_sec.external_pwd) then
4474       return('EXTERNAL');
4475     else
4476       return(null);
4477     end if;
4478   exception
4479     when others then
4480       fnd_message.set_name('FND', 'LDAP_WRAPPER_UPDATE_USER_FAIL');
4481       fnd_message.set_token('USER_NAME', x_user_name);
4482       fnd_message.set_token('REASON', sqlerrm);
4483      app_exception.raise_exception;
4484   end;
4485 exception
4486   when others then
4487     app_exception.raise_exception;
4488 end;
4489 
4490 ----------------------------------------------------------------------------
4491 --
4492 -- ldap_wrapper_update_user (PUBLIC)
4493 --   This is called by the fnd_user_pkg and fnd_web_sec
4494 --   It serves as a helper routine to call fnd_ldap_wrapper.update_user
4495 --   when we need to synch the user update to OID.
4496 -- Note
4497 --   Please note that even this is public procedure, it does not mean for
4498 --   other public usage. This is mainly created as a helper routine to
4499 --   service the user form and the user package.
4500 procedure ldap_wrapper_update_user(x_user_name in varchar2,
4501                                    x_unencrypted_password in varchar2,
4502                                    x_start_date in date,
4503                                    x_end_date in date,
4504                                    x_description in varchar2,
4505                                    x_email_address in varchar2,
4506                                    x_fax in varchar2,
4507                                    x_expire_pwd in pls_integer default 0) is
4508     l_pwd_ret varchar2(100);
4509     l_expire_pwd pls_integer;
4510     l_api_name varchar2(256) := 'ldap_wrapper_udpate_user';
4511 begin
4512 
4513       if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
4514            fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head||'.'||l_api_name,
4515                    'Begin - set l_expire_pwd before calling fnd_ldap_wrapper');
4516       end if;
4517 
4518     -- Bug 13472484 - Using global when called from fnd_web_sec.change_password
4519     -- APIs since the expiration calculation is done in fnd_user_pkg.UpdateUserInternal.
4520     -- where this global is set.
4521     -- Any other calls to this API should use the arg x_expire_pwd.
4522 
4523     if (G_EXPIRE_USER_PWD is not  null) then
4524         l_expire_pwd := G_EXPIRE_USER_PWD;
4525     else
4526         l_expire_pwd := x_expire_pwd;
4527     end if;
4528 
4529     if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
4530           fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head||l_api_name,
4531                   'l_expire_pwd = '||l_expire_pwd);
4532     end if;
4533 
4534 
4535     l_pwd_ret := null;
4536 
4537     l_pwd_ret := ldap_wrp_update_user_helper(x_user_name,
4538           x_unencrypted_password, x_start_date, x_end_date, x_description,
4539           x_email_address, x_fax, l_expire_pwd);
4540     if (l_pwd_ret is not null) then
4541       -- If the return password from ldap is not null, that means ldap
4542       -- is informing us that this user is externally managed so we need
4543       -- to update the password to EXTERNAL.
4544 
4545       if (fnd_log.LEVEL_STATEMENT >= fnd_log.g_current_runtime_level) then
4546            fnd_log.string(FND_LOG.LEVEL_STATEMENT, c_log_head||'.'||l_api_name,
4547                    'set fnd_user pwd to be EXTERNALLY managed.  l_pwd_ret = '||l_pwd_ret);
4548       end if;
4549 
4550       update fnd_user
4551       set encrypted_foundation_password = l_pwd_ret,
4552           encrypted_user_password = l_pwd_ret
4553       where user_name = upper(x_user_name);
4554     end if;
4555 
4556 end;
4557 
4558 
4559 --
4560 -- ldap_wrapper_create_user (PUBLIC)
4561 --   This is called by user form and the fnd_user_pkg.
4562 --   It serves as a helper routine to call fnd_ldap_wrapper.create_user
4563 --   when we need to synch that new FND user to OID.
4564 --   It also takes care of updating fnd_user with the user_guid and oid_pwd
4565 --   coming back from ldap_wrapper layer.
4566 -- Note
4567 --   Please note that even this is public procedure, it does not mean for
4568 --   other public usage. This is mainly created as a helper routine to
4569 --   service the user form and the user package.
4570 
4571 procedure ldap_wrapper_create_user(x_user_name in varchar2,
4572                                    x_unencrypted_password in varchar2,
4573                                    x_start_date in date,
4574                                    x_end_date in date,
4575                                    x_description in varchar2,
4576                                    x_email_address in varchar2,
4577                                    x_fax in varchar2,
4578                                    x_expire_pwd in pls_integer default 0) is
4579 l_user_guid raw(16);
4580 l_oid_pwd varchar2(30);
4581 ret varchar2(1);
4582 reason varchar2(2000);
4583 
4584 begin
4585 
4586   l_user_guid := null;
4587   l_oid_pwd := null;
4588   ldap_wrapper_create_user(x_user_name, x_unencrypted_password,
4589                            x_start_date, x_end_date,
4590                            x_description,x_email_address,x_fax,x_expire_pwd,
4591                            l_user_guid, l_oid_pwd);
4592   if (l_user_guid is not null) then
4593     update fnd_user
4594     set user_guid = l_user_guid
4595     where user_name = x_user_name;
4596   end if;
4597 
4598   if (l_oid_pwd = fnd_web_sec.external_pwd) then
4599     -- Add third argument to not use autonomous transaction when chaning
4600     -- passowrd. This is for bug 5087728
4601     ret := fnd_web_sec.change_password(x_user_name, l_oid_pwd, FALSE);
4602     if (ret = 'N') then
4603       reason := fnd_message.get();
4604       fnd_message.set_name('FND', 'FND_CHANGE_PASSWORD_FAILED');
4605       fnd_message.set_token('USER_NAME', X_USER_NAME);
4606       fnd_message.set_token('REASON', reason);
4607       app_exception.raise_exception;
4608     end if;
4609   end if;
4610 
4611 exception
4612   when others then
4613     app_exception.raise_exception;
4614 end;
4615 
4616 -- end bug 4318754
4617 
4618 --
4619 -- ldap_wrapper_change_user_name (PUBLIC)
4620 --   This is called by user form. When there is user name changed inside
4621 --   User form, we need to synch with ldap.
4622 --
4623 -- Note
4624 --   Please note that even this is public procedure, it does not mean for
4625 --   other public usage. This is mainly created as a helper routine to
4626 --   service the user form and the user package.
4627 procedure ldap_wrapper_change_user_name(x_old_user_name in varchar2,
4628                                         x_new_user_name in varchar2) is
4629 
4630   l_user_guid raw(16);
4631 begin
4632 
4633   l_user_guid := null;
4634 
4635   select user_guid
4636   into l_user_guid
4637   from fnd_user
4638   where user_name = x_old_user_name;
4639 
4640   if (l_user_guid is not null) then
4641   ldap_wrapper_change_user_name(l_user_guid, x_old_user_name, x_new_user_name);
4642   end if;
4643 
4644 exception
4645   when others then
4646     app_exception.raise_exception;
4647 end;
4648 
4649 ----------------------------------------------------------------------------
4650 --
4651 -- form_ldap_wrapper_update_user (PUBLIC)
4652 --   This is called by user form.
4653 --   It serves as a helper routine to call fnd_ldap_wrapper.update_user
4654 --   when we need to synch the user update to OID.
4655 -- Note
4656 --   Please note that even this is public procedure, it does not mean for
4657 --   other public usage. This is mainly created as a helper routine to
4658 --   service the user form.
4659 procedure form_ldap_wrapper_update_user(x_user_name in varchar2,
4660                                         x_unencrypted_password in varchar2,
4661                                         x_start_date in date,
4662                                         x_end_date in date,
4663                                         x_description in varchar2,
4664                                         x_email_address in varchar2,
4665                                         x_fax in varchar2,
4666                                         x_out_pwd in out nocopy varchar2) is
4667     l_end_date date;
4668     l_description varchar2(240);
4669     l_email_address varchar2(240);
4670     l_fax varchar2(80);
4671     l_pwd_ret varchar2(1000);
4672 begin
4673 
4674   -- Bug 5161134
4675   -- If is from Form, we can not use our rule about null means no change.
4676   -- If form passs in null value, that means change it to null.
4677 
4678   -- Bug 11704380
4679   -- On update if the field is null, whether it has been changed or not, the
4680   -- fnd_user_pkg null value is being passed to the ldap APIs.  This is causing
4681   -- OID records to be updated to *NULL* values.  We need to better handle a
4682   -- nulled out value but for the short term we will not pass this char and
4683   -- the OID data as is.
4684 
4685     l_end_date := x_end_date;
4686     l_description := x_description;
4687     l_email_address := x_email_address;
4688     l_fax := x_fax;
4689 
4690   -- Call our wrapper update helper. Passing G_TRUE for expiring password
4691   -- because any password update in USER form should result password
4692   -- expiration.
4693   l_pwd_ret := ldap_wrp_update_user_helper(x_user_name,
4694           x_unencrypted_password, x_start_date, l_end_date, l_description,
4695           l_email_address, l_fax, fnd_ldap_wrapper.G_TRUE );
4696 
4697   -- Return the ldap out password to User form.
4698   x_out_pwd := l_pwd_ret;
4699 
4700 exception
4701   when others then
4702     app_exception.raise_exception;
4703 end;
4704 
4705 ----------------------------------------------------------------------------
4706 -- This routine is for AOL INTERNAL USE ONLY !!!!!!!
4707 --
4708 -- ldap_wrp_update_user_loader
4709 --   This is called by the fnd_user_pkg and fnd_web_sec.
4710 --   It serves as a helper routine to call fnd_ldap_wrapper.update_user
4711 --   when we need to synch the user update to OID.
4712 procedure ldap_wrp_update_user_loader(x_user_name in varchar2,
4713                                    x_hashed_password in varchar2,
4714                                    x_start_date in date,
4715                                    x_end_date in date,
4716                                    x_description in varchar2,
4717                                    x_email_address in varchar2,
4718                                    x_fax in varchar2,
4719                                    x_expire_pwd in pls_integer default 1)
4720 is
4721     l_pwd_ret varchar2(100);
4722     l_user_guid raw(16);
4723     l_result number;
4724     reason varchar2(2000);
4725     userid number; -- bug 5162136
4726 begin
4727 
4728   l_user_guid := null;
4729   l_result := null;
4730   l_pwd_ret := null;
4731   userid := null;
4732 
4733   select user_guid, user_id into l_user_guid, userid
4734   from fnd_user
4735   where user_name = x_user_name;
4736 
4737   if (l_user_guid is null) then
4738     return;
4739   end if;
4740 
4741   fnd_ldap_wrapper.update_user(l_user_guid, x_user_name,
4742         x_hashed_password, x_start_date, x_end_date, x_description,
4743         x_email_address, x_fax, x_expire_pwd, l_pwd_ret, l_result);
4744 
4745   if (l_result <> fnd_ldap_wrapper.G_SUCCESS) then
4746     reason := fnd_message.get();
4747     fnd_message.set_name('FND', 'LDAP_WRAPPER_UPDATE_USER_FAIL');
4748     fnd_message.set_token('USER_NAME', x_user_name);
4749     fnd_message.set_token('REASON', reason);
4750     app_exception.raise_exception;
4751   end if;
4752 
4753   if (l_pwd_ret = fnd_web_sec.external_pwd) then
4754      update fnd_user
4755      set encrypted_foundation_password = 'EXTERNAL',
4756          encrypted_user_password = 'EXTERNAL'
4757      where user_name = upper(x_user_name);
4758   end if;
4759 
4760   exception
4761     when others then
4762       fnd_message.set_name('FND', 'LDAP_WRAPPER_UPDATE_USER_LOADER_FAIL');
4763       fnd_message.set_token('USER_NAME', x_user_name);
4764       fnd_message.set_token('REASON', sqlerrm);
4765      app_exception.raise_exception;
4766 
4767 end;
4768 
4769 end FND_USER_PKG;