REM dbdrv: sql ~PROD ~PATH ~FILE none none none package &phase=plb \ REM dbdrv: checkfile:~PROD:~PATH:~FILE /*=======================================================================+ | Copyright (c) 1999 Oracle Corporation Redwood Shores, California, USA| | All rights reserved. | +=======================================================================+ | FILENAME | wfhtmb.pls | DESCRIPTION | PL/SQL body for package: WFA_HTML | NOTE | There is a dependency on dynamic sql. | Must have Oracle 8.1.5 or above. | | MODIFICATION LOG: | 01/2002 JWSMITH BUG 2001012 - Increased luser, lowner, lfromuser,ldt, | ltmpname, username, admin_role, t_owner, t_user, t_fromuser, | t_delegatedto, s0, recipient, orig_recipient, | uos, ros, oos, sess_username, disprole, titlerole, | l_forwardee, l_username, l_name to varchar2(320), | role display_name (realname) to varchar2(360) | 02/2002 JWSMITH BUG 2167012 - Moved owa_util.header_close call to after | the owa_util.redirect call in ResponseFrame. | 04/2002 JWSMITH BUG 2232218 - Added new query to handle the case | when you want to query notifications by role name. | 09/2002 JWSMITH BUG 1691538 - Added javascript to valide the nid | on the Find Notification Screen. | 11/2002 CTILLEY BUG 2664679 - only validate nid if in admin mode else | error on page occurs for non-Admin users. | 12/2002 JWSMITH BUG 2664679/2719596 - Also need to change the submit | button in Find routine to not call the javascript unless in | admin mode. *=======================================================================*/ SET VERIFY OFF WHENEVER SQLERROR EXIT FAILURE ROLLBACK; WHENEVER OSERROR EXIT FAILURE ROLLBACK; set arraysize 1 set scan off create or replace package body WFA_HTML as /* $Header: wfhtmb.pls 26.64 2005/03/11 06:18:55 anachatt ship $ */ -- Bug# 2236250 exception to handle invalid number invalid_number exception; pragma EXCEPTION_INIT(invalid_number, -6502); g_priority varchar2(2000); g_newline varchar2(1) := wf_core.newLine; g_wfInstall varchar2(15) := wf_core.translate('WF_INSTALL'); -- -- Error (PRIVATE) -- Print a page with an error message. -- Errors are retrieved from these sources in order: -- 1. wf_core errors -- 2. Oracle errors -- 3. Unspecified INTERNAL error -- procedure Error as error_name varchar2(30); error_message varchar2(2000); error_stack varchar2(32000); begin htp.htmlOpen; htp.headOpen; htp.title(wf_core.translate('ERROR')); htp.headClose; begin wfa_sec.Header(background_only=>TRUE); exception when others then htp.bodyOpen; end; wf_core.get_error(error_name, error_message, error_stack); --Bug 4215720 error_message:=wf_core.substitutespecialchars(error_message); error_stack:=wf_core.substitutespecialchars(error_stack); htp.p(''); htp.p(''); htp.br; htp.br; htp.p('
'); --print the actual page, with a button in top right to go back htp.p(''||wf_core.translate('ERROR')||': '); --print error message with hyperlink to stack htp.p(''); if (error_name is not null) then htp.p(error_message); else htp.p(sqlerrm); end if; htp.p(''); htp.p('
'); htp.br; htp.br; htp.tableopen (cattributes =>'align=CENTER border=0 summary=""'); htp.tableRowOpen; htp.p(''); wfa_html.create_reg_button ('javascript:history.back()', wf_core.translate ('WFMON_OK'), wfa_html.image_loc, null, wf_core.translate ('WFMON_OK')); htp.p(''); htp.tableRowClose; htp.tableClose; wfa_sec.Footer; htp.htmlClose; end Error; -- -- -- Login -- Generate login page. -- IN -- message - optional login message -- NOTE -- This page is only used to enable access when no external security -- is installed. Normally users are authenticated by the chosen -- security system (IC, WebServer native, etc) and can then access -- the Workflow Notification pages (Worklist, Detail) directly. -- procedure Login( message in varchar2, i_direct in varchar2) as c_language VARCHAR2(80); begin -- Get the global language preference since we don't know who the -- user is yet... c_language := NVL(wf_pref.get_pref ('-WF_DEFAULT-', 'LANGUAGE'), 'AMERICAN'); c_language := ''''||c_language||''''; dbms_session.set_nls('NLS_LANGUAGE' , c_language); -- Set the language to the default language for the system htp.htmlOpen; htp.headOpen; htp.title(wf_core.translate('WFA_LOGIN_REQUEST')); wfa_html.create_help_function('wf/links/log.htm?LOGIN'); htp.headClose; wfa_sec.Header(background_only=>FALSE, inc_lov_applet=>FALSE); htp.p('
'); -- bug 1838410 if (i_direct is not null) then htp.formHidden('i_direct', i_direct); end if; if (message is not null) then htp.header(4, wf_core.translate(message)); htp.br; end if; htp.br; htp.tableOpen(calign=>'CENTER', cattributes=>'summary=""'); htp.tableRowOpen; htp.tableData('', 'Right', cattributes=>'id=""'); htp.tableData(htf.formText('User_ID', 25, cattributes=>'id="i_user_id"'), 'Left', cattributes=>'id=""'); htp.tableRowClose; htp.tableRowOpen; htp.tableData('', 'Right', cattributes=>'id=""'); htp.tableData(htf.formPassword('Password', 25, cattributes=>'id="i_password"'), 'Left', cattributes=>'id=""'); htp.tableRowClose; htp.tableClose; htp.centerClose; htp.br; htp.formClose; htp.tableopen (calign=>'CENTER', cattributes=>'summary=""'); htp.tableRowOpen; htp.p(''); wfa_html.create_reg_button ('javascript:document.WFA_LOGIN.submit()', wf_core.translate ('LOGIN'), wfa_html.image_loc, 'FNDJLFOK.gif', wf_core.translate ('LOGIN')); htp.p(''); htp.tableRowClose; htp.tableClose; wfa_sec.Footer; htp.htmlClose; exception when others then rollback; wf_core.context('Wfa_Html', 'Login'); wfa_html.Error; end Login; -- -- Viewer -- Validate user from Login page, then show worklist. -- IN -- user_id - user name -- password - user password -- NOTE -- This page is only used to enable access when no external security -- is installed. Normally users are authenticated by the chosen -- security system (IC, WebServer native, etc) and can then access -- the Workflow Notification pages (Worklist, Detail) directly. -- procedure Viewer( user_id in varchar2, password in varchar2, i_direct in varchar2) as s0 varchar2(320); -- dummy username varchar2(320); realname varchar2(360); begin -- Validate the user if (user_id is null) then -- No username entered wfa_html.Login('WFA_ENTER_ID'); return; end if; username := upper(user_id); begin wfa_sec.CreateSession(username, password); exception when others then if (wf_core.error_name='WFSEC_USER_PASSWORD') then -- Bad username or password wf_core.clear; wfa_html.Login('WFA_ILLEGAL_IDP'); return; end if; -- Raise any other error message raise; end; if (i_direct is null) then -- Go to home page Wfa_Html.Home; else -- Fix for bug 1838410 -- Instead of navigating to the home page, we will go directly to the URL -- specified in i_direct and the user will now be authenticated. We are -- calling the function within a frame. -- Example: E-mail notifications with send_accesskey=N. htp.p(''); htp.p(''); htp.p(''); htp.p(''); htp.p(''); htp.p(''); htp.p(''); htp.p(''); htp.p(''); end if; exception when others then rollback; wf_core.context('Wfa_Html', 'Viewer', user_id, password); wfa_html.Error; end Viewer; -- -- Find -- Filter page to find notifications of user -- procedure Find is username varchar2(320); -- Username to query realname varchar2(360); -- Display name of username admin_role varchar2(320); -- Role for admin mode s0 varchar2(2000); lang_codeset varchar2(50); -- Language Codeset from environment -- (e.g. WE8ISO8859P1) l_message varchar2(240) := wfa_html.replace_onMouseOver_quotes(wf_core.translate ('WFPREF_LOV')); admin_mode boolean; -- TRUE if user has admin role priviledge l_url varchar2(1000); l_media varchar2(240) := wfa_html.image_loc; l_icon varchar2(30) := 'FNDILOV.gif'; l_onmouseover varchar2(240) := wfa_html.replace_onMouseOver_quotes(wf_core.translate('WFA_FIND_USER')); uorig_system varchar2(30); -- User orig_system for indexes uorig_system_id number; -- User orig_system_id for indexes cursor lkcurs(lktype in varchar2) is select WL.MEANING, WL.LOOKUP_CODE from WF_LOOKUPS WL where WL.LOOKUP_TYPE = lktype order by WL.MEANING; -- Lookup for Item Type (regular role) cursor itcurs(role varchar2, uos varchar2, uosid number) is select unique WIT.DISPLAY_NAME, WN.MESSAGE_TYPE from WF_NOTIFICATIONS WN, WF_ITEM_TYPES_VL WIT where WN.MESSAGE_TYPE = WIT.NAME and WN.RECIPIENT_ROLE in (select ROLE_NAME from WF_USER_ROLES where USER_ORIG_SYSTEM = uos and USER_ORIG_SYSTEM_ID = uosid and USER_NAME = role) order by WIT.DISPLAY_NAME; -- Lookup for Item Type (admin role) -- Cursor sql changed for bug 1953214. No longer include WF_NOTIFICATIONS -- in sql. Performance improvement. cursor aitcurs is select WIT.DISPLAY_NAME,WIT.NAME MESSAGE_TYPE from WF_ITEM_TYPES_VL WIT order by WIT.DISPLAY_NAME; ittype itcurs%rowtype; aittype aitcurs%rowtype; begin -- Check session and current user wfa_sec.GetSession(username); username := upper(username); wf_directory.GetRoleInfo(username, realname, s0, s0, s0, s0); -- Check Admin Priviledge admin_role := wf_core.translate('WF_ADMIN_ROLE'); if (admin_role = '*' or Wf_Directory.IsPerformer(username, admin_role)) then admin_mode := TRUE; else admin_mode := FALSE; end if; -- Get language codeset lang_codeset := substr(userenv('LANGUAGE'),instr(userenv('LANGUAGE'),'.')+1, length(userenv('LANGUAGE'))); -- Set page title htp.htmlOpen; htp.headOpen; htp.title(wf_core.translate('WFA_FINDTITLE')||' - '||realname); wfa_html.create_help_function('wf/links/fin.htm?FINDNOT'); fnd_document_management.get_open_dm_display_window; -- CTILLEY BUG 2664679 - only validate nid if in admin mode else error on -- page occurs for non-Admin users. if (admin_mode) then --JWSMITH BUG 1691538 - add javascript to validate nid htp.p('' || wf_core.newline); end if; htp.headClose; -- Page header wfa_sec.Header(FALSE, '', wf_core.translate('WFA_FINDTITLE'), TRUE); htp.formOpen(curl=>owa_util.get_owa_service_path||'wfa_html.WorkList', cmethod=>'Post', cattributes=>'TARGET="_top" NAME="WF_FIND"'); htp.tableOpen(calign=>'CENTER', cattributes=>'border=0 summary=""'); -- Add following fields if current user has WF_ADMIN_ROLE privileges if (admin_mode) then -- Notification ID field htp.tableRowOpen; htp.tableData(cvalue=>'', calign=>'right', cattributes=>'id=""'); htp.tableData(htf.formText(cname=>'nid', csize=>'8', cmaxlength=>'15', cattributes=>'id="i_nid"'), calign=>'left', cattributes=>'id=""'); htp.tableRowClose; htp.tableRowOpen; htp.tableData(cvalue=>' ', calign=>'right', cattributes=>'id=""'); htp.tableData(cvalue=>''||wf_core.translate('OR')||'', calign=>'left', cattributes=>'id=""'); htp.tableRowClose; -- Owner Field htp.tableRowOpen; htp.tableData(cvalue=>'', calign=>'right', cattributes=>'id=""'); htp.formHidden('owner', null); -- Bug 1298601 : added call to replace_onMouseOver_quotes to p_display_name -- add LOV here: Note:bottom is name of frame. -- Note: The REPLACE function replaces all the space characters with -- the proper escape sequence. l_url := 'javascript:fnd_open_dm_display_window('||''''|| REPLACE('wf_lov.display_lov?p_lov_name='||'owner'|| '&p_display_name='||'WFA_FIND_USER'|| '&p_validation_callback=wfa_html.wf_user_val'|| '&p_dest_hidden_field=top.opener.parent.document.WF_FIND.owner.value'|| '&p_current_value=top.opener.parent.document.WF_FIND.display_owner.value'|| '&p_display_key='||'Y'|| '&p_dest_display_field=top.opener.parent.document.WF_FIND.display_owner.value', ' ', '%20')||''''||',500,500)'; -- print everything together so there is no gap. htp.tabledata(htf.formText(cname=>'display_owner', csize=>30, cmaxlength=>240, cattributes=>'id="i_owner"')|| ''|| ''||
                    l_message||'', cattributes=>'id=""'); htp.tableRowClose; -- To User Field htp.tableRowOpen(cvalign=>'middle'); htp.tableData(cvalue=>'', calign=>'right', cattributes=>'id=""'); htp.formHidden('user', null); -- add LOV here: Note:bottom is name of frame. -- Note: The REPLACE function replaces all the space characters with -- the proper escape sequence. l_url := 'javascript:fnd_open_dm_display_window('||''''|| REPLACE('wf_lov.display_lov?p_lov_name='||'user'|| '&p_display_name='||'WFA_FIND_USER'|| '&p_validation_callback=wfa_html.wf_user_val'|| '&p_dest_hidden_field=top.opener.parent.document.WF_FIND.user.value'|| '&p_current_value=top.opener.parent.document.WF_FIND.display_user.value'|| '&p_display_key='||'Y'|| '&p_dest_display_field=top.opener.parent.document.WF_FIND.display_user.value', ' ', '%20')||''''||',500,500)'; -- print everything together so ther is no gap. htp.tabledata(htf.formText(cname=>'display_user', csize=>30, cmaxlength=>240, cattributes=>'id="i_display_user"')|| ''|| ''||
                    l_message||'', cattributes=>'id=""'); htp.tableRowClose; end if; -- From User Field htp.tableRowOpen(cvalign=>'middle'); htp.tableData(cvalue=>'', calign=>'right', cattributes=>'id=""'); htp.formHidden('fromuser', null); -- add LOV here: Note:bottom is name of frame. -- Note: The REPLACE function replaces all the space characters with -- the proper escape sequence. l_url := 'javascript:fnd_open_dm_display_window('||''''|| REPLACE('wf_lov.display_lov?p_lov_name='||'fromuser'|| '&p_display_name='||'WFA_FIND_USER'|| '&p_validation_callback=wfa_html.wf_user_val'|| '&p_dest_hidden_field=top.opener.parent.document.WF_FIND.fromuser.value'|| '&p_current_value=top.opener.parent.document.WF_FIND.display_fromuser.value'|| '&p_display_key='||'Y'|| '&p_dest_display_field=top.opener.parent.document.WF_FIND.display_fromuser.value', ' ', '%20')||''''||',500,500)'; -- print everything together so there is no gap. htp.tabledata(htf.formText(cname=>'display_fromuser', csize=>30, cmaxlength=>360, cattributes=>'id="i_display_fromuser"')|| ''|| ''||
                  l_message||'', cattributes=>'id=""'); htp.tableRowClose; -- Status field htp.tableRowOpen; htp.tableData(cvalue=>'', calign=>'right', cattributes=>'id=""'); htp.p(''); htp.formSelectOpen('status', cattributes=>'id="i_status"'); htp.formSelectOption(cvalue=>wf_core.translate('ALL'), cattributes=>'value=*'); for status in lkcurs('WF_NOTIFICATION_STATUS') loop if (status.lookup_code = 'OPEN') then htp.formSelectOption(cvalue=>status.meaning, cselected => 'SELECTED', cattributes=>'value='||status.lookup_code); else htp.formSelectOption(cvalue=>status.meaning, cattributes=>'value='||status.lookup_code); end if; end loop; htp.formSelectClose; htp.p(''); htp.tableRowClose; -- Type field htp.tableRowOpen; htp.tableData(cvalue=>'', calign=>'right', cattributes=>'id=""'); htp.p(''); htp.formSelectOpen('ittype', cattributes=>'id="i_ittype"'); htp.formSelectOption(cvalue=>wf_core.translate('ALL'), cselected => 'SELECTED', cattributes=>'value=*'); if (admin_mode) then for aittype in aitcurs loop /* ** Take care of the case where the item type has a space in it. ** We used a + to represent the space in the list of values since you ** can escape it in a poplist and pass it through the post. */ htp.formSelectOption(cvalue=>aittype.display_name, cattributes=>'value='|| REPLACE(aittype.message_type,' ','+')); end loop; else Wf_Directory.GetRoleOrigSysInfo(username,uorig_system,uorig_system_id); for ittype in itcurs(username, uorig_system, uorig_system_id) loop /* ** Take care of the case where the item type has a space in it. ** We used a + to represent the space in the list of values since you ** can escape it in a poplist and pass it through the post. */ htp.formSelectOption(cvalue=>ittype.display_name, cattributes=>'value='|| REPLACE(ittype.message_type,' ','+')); end loop; end if; htp.formSelectClose; htp.p(''); htp.tableRowClose; -- Subject field htp.tableRowOpen; htp.tableData(cvalue=>'', calign=>'right', cattributes=>'id=""'); htp.tableData(htf.formText(cname=>'msubject', csize=>'40', cmaxlength=>'80', cattributes=>'id="i_subject"'), calign=>'left', cattributes=>'id=""'); htp.tableRowClose; -- Sent Date field htp.tableRowOpen; htp.tableData(cvalue=>'', calign=>'right', cattributes=>'id=""'); htp.tableData(htf.formText(cname=>'beg_sent', csize=>'9',cmaxlength=>'15', cattributes=>'id="i_beg_date"')|| ' - ' || htf.formText(cname=>'end_sent', csize=>'9', cmaxlength=>'15', cattributes=>'id="i_beg_date"'), calign=>'left', cattributes=>'id=""'); htp.tableRowClose; -- Due Date field htp.tableRowOpen; htp.tableData(cvalue=>'', calign=>'right', cattributes=>'id=""'); htp.tableData(htf.formText(cname=>'beg_due', csize=>'9', cmaxlength=>'15', cattributes=>'id="i_due_date"')|| ' - ' || htf.formText(cname=>'end_due', csize=>'9', cmaxlength=>'15', cattributes=>'id="i_due_date"'), calign=>'left', cattributes=>'id=""'); htp.tableRowClose; -- Priority field htp.tableRowOpen; htp.tableData(cvalue=>'', calign=>'right', cattributes=>'id=""'); htp.p(''); htp.formSelectOpen('priority', cattributes=>'id="i_priority"'); htp.formSelectOption(cvalue=>wf_core.translate('ALL'), cselected => 'SELECTED', cattributes=>'value=*'); htp.formSelectOption(cvalue=>wf_core.translate('HIGH'), cattributes=>'value="HIGH"'); htp.formSelectOption(cvalue=>wf_core.translate('NORMAL'), cattributes=>'value="NORMAL"'); htp.formSelectOption(cvalue=>wf_core.translate('LOW'), cattributes=>'value="LOW"'); htp.formSelectClose; htp.p(''); htp.tableRowClose; -- Reset Cookie!!! htp.formHidden('resetcookie', 1); htp.formHidden('fromfindscreen', 1); if (admin_mode=FALSE) then -- Do not allow admin mode to have "Delegated by me" -- Delegated by me field htp.tableRowOpen; htp.tableData(cvalue=>'&'||'nbsp;', cattributes=>'id=""'); htp.formHidden('delegatedto', null); -- add LOV here: Note:bottom is name of frame. -- Note: The REPLACE function replaces all the space characters with -- the proper escape sequence. l_url := 'javascript:fnd_open_dm_display_window('||''''|| REPLACE('wf_lov.display_lov?p_lov_name='||'owner'|| '&p_display_name='||'WFA_FIND_USER'|| '&p_validation_callback=wfa_html.wf_user_val'|| '&p_dest_hidden_field=top.opener.parent.document.WF_FIND.delegatedto.value'|| '&p_current_value=top.opener.parent.document.WF_FIND.display_delegatedto.value'|| '&p_display_key='||'Y'|| '&p_dest_display_field=top.opener.parent.document.WF_FIND.display_delegatedto.value', ' ', '%20')||''''||',500,500)'; htp.p(''); htp.formCheckbox(cname=>'delegated_by_me', cvalue=>1); htp.p(''); htp.formText(cname=>'display_delegatedto', csize=>30, cmaxlength=>240, cattributes=>'id="i_ldt"'); htp.p(''|| ''||
                    l_message||''); htp.p(''); htp.tableRowClose; end if; htp.tableClose; htp.formClose; -- Add submit button htp.tableopen (calign=>'CENTER', cattributes=>'summary=""'); htp.tableRowOpen; htp.p(''); -- JWSMITH BUG 1691538/2719596 - Changed to call javascript function to -- validate the nid field. if (admin_mode) then wfa_html.create_reg_button ('javascript:SubmitValidate()', wf_core.translate ('FIND'), wfa_html.image_loc, 'fndfind.gif', wf_core.translate ('FIND')); else wfa_html.create_reg_button ('javascript:document.WF_FIND.submit()', wf_core.translate ('FIND'), wfa_html.image_loc, 'fndfind.gif', wf_core.translate ('FIND')); end if; htp.p(''); htp.tableRowClose; htp.tableClose; wfa_sec.Footer; htp.htmlClose; exception when others then rollback; wf_core.context('Wfa_Html', 'Find'); wfa_html.Error; end Find; -- -- GetPriorityBounds -- Get the upper bound and lower bound of certain priority -- IN -- priority - Value of priority -- Valid values are HIGH, NORMAL, LOW and * -- IN OUT -- low - lower bound of numeric priority value -- up - upper bound of numeric priority value -- RETURNS -- TRUE - successfully return the boundaries -- FALSE - failed to translate -- function GetPriorityBounds( priority in varchar2, low in out nocopy pls_integer, up in out nocopy pls_integer) return boolean as -- minint pls_integer := 0; -- maxint pls_integer := 2147483647; /* 2^31 - 1 */ -- -- Priority Range should be 1 - 99 -- For supporting some possible out of range value in the past, -- we set the range a bit higher -- minint pls_integer := 0; maxint pls_integer := 1000000; begin if (priority = '*') then low := minint; up := maxint; elsif (priority = 'HIGH') then low := minint; up := 33; elsif (priority = 'NORMAL') then low := 34; up := 66; elsif (priority = 'LOW') then low := 67; up := maxint; else low := -1; up := -1; return FALSE; end if; return TRUE; end GetPriorityBounds; -- -- GetPriorityIcon -- Get the icon of certain numeric priority -- IN -- priority - Value of priority -- Valid values are minint - maxint -- defined in GetPriorityBounds -- -- RETURNS -- Icon - location of an icon -- function GetPriorityIcon( priority in pls_integer) return varchar2 as begin if (priority < 34) /* HIGH */ then WFA_HTML.g_priority := WF_CORE.Translate('WFJSP_HIGH_PRIORITY'); return(wfa_html.image_loc||'high.gif'); elsif (priority > 66) /* LOW */ then WFA_HTML.g_priority := WF_CORE.Translate('WFJSP_LOW_PRIORITY'); return(wfa_html.image_loc||'low.gif'); else /* NORMAL */ return null; end if; end GetPriorityIcon; -- -- WorkList -- Construct the worklist (summary page) for user. -- IN -- orderkey - Key to order by (default PRIORITY) -- Valid values are PRIORITY, MESSAGE_TYPE, SUBJECT, BEGIN_DATE, -- DUE_DATE, END_DATE, STATUS. -- status - Status to query (default OPEN) -- Valid values are OPEN, CLOSED, CANCELED, ERROR, *. -- user - User to query notifications for. If null query user currently -- logged in. -- Note: Only a user in role WF_ADMIN_ROLE can query a user other -- than the current user. -- fromlogin - flag to indicate if coming from apps login screen, -- - if non-zero, force an exception -- - so that cookie value is not being used -- procedure WorkList( nid in number, orderkey in varchar2, status in varchar2, owner in varchar2 , display_owner in varchar2, user in varchar2, display_user in varchar2, fromuser in varchar2, display_fromuser in varchar2, ittype in varchar2, msubject in varchar2, beg_sent in varchar2, end_sent in varchar2, beg_due in varchar2, end_due in varchar2, priority in varchar2, delegatedto in varchar2, display_delegatedto in varchar2, delegated_by_me in number, resetcookie in number, clearbanner in varchar2, fromfindscreen in number, fromlogin in number) as cookie owa_cookie.cookie; c1 pls_integer; -- First colon for parsing cookie c2 pls_integer; -- Second colon for parsing cookie c3 pls_integer; -- Third colon for parsing cookie c4 pls_integer; -- Fourth colon for parsing cookie c5 pls_integer; -- Fifth colon for parsing cookie c6 pls_integer; -- Sixth colon for parsing cookie c7 pls_integer; -- Seventh colon for parsing cookie c8 pls_integer; -- Eighth colon for parsing cookie c9 pls_integer; -- Nineth colon for parsing cookie c10 pls_integer; -- Tenth colon for parsing cookie c11 pls_integer; -- Eleventh colon for parsing cookie c12 pls_integer; -- Twelveth colon for parsing cookie c13 pls_integer; -- Thirteenth colon for parsing cookie c14 pls_integer; -- Fourteenth colon for parsing cookie lnid number; -- Nid retrieved from cookie lorderkey varchar2(30); -- Orderkey retrieved from cookie lstatus varchar2(30); -- Status retrieved from cookie luser varchar2(320); -- User retrieved from cookie lowner varchar2(320); -- Owner retrieved from cookie lfromuser varchar2(320); -- From Role retrieved from cookie littype varchar2(8); -- Item Type retrieved from cookie lsubject varchar2(80); -- Subject retrieved from cookie lbeg_sent varchar2(15); -- Begin Sent Date retrieved from cookie lend_sent varchar2(15); -- End Sent Date retrieved from cookie lbeg_due varchar2(15); -- Begin Due Date retrieved from cookie lend_due varchar2(15); -- End Due Date retrieved from cookie lpriority varchar2(8); -- Priority retrieved from cookie lshowto varchar2(1); -- Show the To field ldt varchar2(320); -- Delegated to user ldbm pls_integer; -- Delegated_by_me retrieved from cookie bad_cookie exception; -- Syntax error in cookie invalid_cookie exception; -- Exception so that we don't use values in cookie ltmpname varchar2(410); -- Bigger than username because of the possible -- escape single quotes username varchar2(320); -- Username to query colon pls_integer; -- Magic orig_system decoder realname varchar2(360); -- Display name of username admin_role varchar2(320); -- Role for admin mode s0 varchar2(2000); -- Dummy n_priority varchar2(80); -- priority icon usercolon pls_integer; -- Check if username is a R n_response varchar2(80); -- required response icon showothers pls_integer := 0; isadmin boolean := false; t_owner varchar2(320) := owner; t_user varchar2(320) := user; t_fromuser varchar2(320) := fromuser; t_delegatedto varchar2(320) := delegatedto; -- Any existence of response attribute constitutes a response required. cursor attrs(mnid in number) is select MA.NAME from WF_NOTIFICATION_ATTRIBUTES NA, WF_MESSAGE_ATTRIBUTES_VL MA, WF_NOTIFICATIONS N where N.NOTIFICATION_ID = mnid and NA.NOTIFICATION_ID = N.NOTIFICATION_ID and MA.MESSAGE_NAME = N.MESSAGE_NAME and MA.MESSAGE_TYPE = N.MESSAGE_TYPE and MA.NAME = NA.NAME and MA.SUBTYPE = 'RESPOND'; result attrs%rowtype; -- -- Variables for the above cursors. -- Make sure they are in sync with the underlying table in the future. -- nf_nid number; nf_priority number; nf_recipient varchar2(4000); -- was 80 nf_message_type varchar2(4000); -- was 80 nf_subject varchar2(4000); -- was 240 nf_begin_date varchar2(4000); nf_due_date varchar2(4000); nf_end_date varchar2(4000); nf_display_status varchar2(4000); -- was 80 nf_status varchar2(8); nf_p0 pls_integer; nf_p1 pls_integer; nf_language varchar2(4); nf_from_user varchar2(4000); nf_to_user varchar2(4000); -- For Worklist Engine inTab Wf_Worklist_Engine.colTabType; outTab Wf_Worklist_Engine.wrkTabType; totalrow number; i pls_integer; -- Default worklist cursor cursor wl_def_cursor (uname varchar2, uos varchar2, uosid number) is select NID, PRIORITY, LANGUAGE, MESSAGE_TYPE, RECIPIENT_ROLE, SUBJECT, BEGIN_DATE, DUE_DATE, END_DATE, DISPLAY_STATUS, STATUS, FROM_USER, TO_USER from WF_WORKLIST_V where (RECIPIENT_ROLE = uname or RECIPIENT_ROLE in (select WUR.ROLE_NAME from WF_USER_ROLES WUR where WUR.USER_ORIG_SYSTEM = uos and WUR.USER_ORIG_SYSTEM_ID = uosid and WUR.USER_NAME = uname)) and STATUS = 'OPEN' order by PRIORITY, BEGIN_DATE DESC; -- DLAM - Add RECIPIENT_ROLE = uname above to achieve what the sql below -- does. -- JWSMITH BUG2232218 - Added cursor to retrieve by role name /* cursor wl_role_cursor (uname varchar2, oos varchar2, oosid number) is select NID, PRIORITY, LANGUAGE, MESSAGE_TYPE, RECIPIENT_ROLE, SUBJECT, BEGIN_DATE, DUE_DATE, END_DATE, DISPLAY_STATUS, STATUS, FROM_USER, TO_USER from WF_WORKLIST_V where RECIPIENT_ROLE in (select WUR.ROLE_NAME from WF_USER_ROLES WUR where WUR.ROLE_ORIG_SYSTEM = oos and WUR.ROLE_ORIG_SYSTEM_ID = oosid and WUR.ROLE_NAME = uname) and STATUS = 'OPEN' order by PRIORITY, BEGIN_DATE DESC; */ -- Default worklist cursor with different order key cursor wl_def_s_cursor (uname varchar2, uos varchar2, uosid number) is select NID, PRIORITY, LANGUAGE, MESSAGE_TYPE, RECIPIENT_ROLE, SUBJECT, BEGIN_DATE, DUE_DATE, END_DATE, DISPLAY_STATUS, STATUS, FROM_USER, TO_USER from WF_WORKLIST_V where RECIPIENT_ROLE in (select WUR.ROLE_NAME from WF_USER_ROLES WUR where WUR.USER_ORIG_SYSTEM = uos and WUR.USER_ORIG_SYSTEM_ID = uosid and WUR.USER_NAME = uname) and STATUS = 'OPEN' order by decode(upper(Worklist.lorderkey), 'MESSAGE_TYPE', MESSAGE_TYPE, 'FROMUSER', FROM_USER, 'TOUSER', TO_USER, 'SUBJECT', SUBJECT, 'BEGIN_DATE', to_char(BEGIN_DATE, 'J.SSSSS'), 'DUE_DATE', to_char(DUE_DATE, 'J.SSSSS'), 'END_DATE', to_char(END_DATE, 'J.SSSSS')); -- Simple worklist query cursor cursor wl_query_cursor (uname varchar2, uos varchar2, uosid number, p0 pls_integer, p1 pls_integer) is select NID, PRIORITY, LANGUAGE, MESSAGE_TYPE, RECIPIENT_ROLE, SUBJECT, BEGIN_DATE, DUE_DATE, END_DATE, DISPLAY_STATUS, STATUS, FROM_USER, TO_USER from WF_WORKLIST_V where RECIPIENT_ROLE in (select WUR.ROLE_NAME from WF_USER_ROLES WUR where WUR.USER_ORIG_SYSTEM = uos and WUR.USER_ORIG_SYSTEM_ID = uosid and WUR.USER_NAME = uname) and ITEM_TYPE = decode(Worklist.littype,'*',ITEM_TYPE, Worklist.littype) and STATUS = decode(Worklist.lstatus, '*', STATUS, '', STATUS, Worklist.lstatus) and ((BEGIN_DATE is null and Worklist.lbeg_sent = '*' and Worklist.lend_sent = '*') or BEGIN_DATE between decode(Worklist.lbeg_sent, '*', BEGIN_DATE, to_date(Worklist.lbeg_sent)) and decode(Worklist.lend_sent, '*', BEGIN_DATE, to_date(Worklist.lend_sent)+1-(1/(24*60*60)))) and ((DUE_DATE is null and Worklist.lbeg_due = '*' and Worklist.lend_due = '*') or DUE_DATE between decode(Worklist.lbeg_due, '*', DUE_DATE, to_date(Worklist.lbeg_due)) and decode(Worklist.lend_due, '*', DUE_DATE, to_date(Worklist.lend_due)+1-(1/(24*60*60)))) and PRIORITY between p0 and p1 order by PRIORITY, BEGIN_DATE DESC; -- NID cursor cursor wl_nid_cursor(xnid number) is select NID, PRIORITY, LANGUAGE, MESSAGE_TYPE, RECIPIENT_ROLE, SUBJECT, BEGIN_DATE, DUE_DATE, END_DATE, DISPLAY_STATUS, STATUS, FROM_USER, TO_USER from WF_WORKLIST_V where NID = xnid; -- General Admin cursor cursor wl_admin_g_cursor(p0 pls_integer, p1 pls_integer) is select /*+ ORDERED INDEX (W.WN,WF_NOTIFICATIONS_N1) USE_NL (W.WN W.WIT W.WL) */ W.NID ,W.PRIORITY ,W.STATUS ,W.LANGUAGE ,W.MESSAGE_TYPE MESSAGE_TYPE ,W.RECIPIENT_ROLE RECIPIENT_ROLE ,W.SUBJECT SUBJECT ,to_char(W.BEGIN_DATE) BEGIN_DATE ,to_char(W.DUE_DATE) DUE_DATE ,to_char(W.END_DATE) END_DATE ,W.DISPLAY_STATUS DISPLAY_STATUS ,W.FROM_USER FROM_USER ,W.TO_USER TO_USER ,NA1.TEXT_VALUE from WF_WORKLIST_V W, WF_NOTIFICATION_ATTRIBUTES NA1 where W.NID = NA1.NOTIFICATION_ID (+) and NA1.NAME (+) = '#FROM_ROLE' and (luser = '*' or (RECIPIENT_ROLE in (select WUR.ROLE_NAME from WF_USER_ROLES WUR where WUR.USER_NAME = luser) or RECIPIENT_ROLE = luser)) and (lowner = '*' or (ORIGINAL_RECIPIENT in (select WUR.ROLE_NAME from WF_USER_ROLES WUR where WUR.USER_NAME = lowner) or ORIGINAL_RECIPIENT = lowner)) and (littype = '*' or (ITEM_TYPE = littype)) and (lstatus is null or lstatus = '*' or (STATUS = lstatus)) and (lsubject = '*' or (SUBJECT like '%'||upper(lsubject)||'%')) and ((BEGIN_DATE is null and Worklist.lbeg_sent = '*' and Worklist.lend_sent = '*') or BEGIN_DATE between decode(Worklist.lbeg_sent, '*', BEGIN_DATE, to_date(Worklist.lbeg_sent)) and decode(Worklist.lend_sent, '*', BEGIN_DATE, to_date(Worklist.lend_sent)+1-(1/(24*60*60)))) and ((DUE_DATE is null and Worklist.lbeg_due = '*' and Worklist.lend_due = '*') or DUE_DATE between decode(Worklist.lbeg_due, '*', DUE_DATE, to_date(Worklist.lbeg_due)) and decode(Worklist.lend_due, '*', DUE_DATE, to_date(Worklist.lend_due)+1-(1/(24*60*60)))) and PRIORITY between p0 and p1 and (lfromuser = '*' or (NA1.TEXT_VALUE = lfromuser)) order by decode(upper(lorderkey), 'MESSAGE_TYPE', MESSAGE_TYPE, 'SUBJECT', SUBJECT, 'BEGIN_DATE', to_char(W.BEGIN_DATE, 'J.SSSSS'), 'DUE_DATE', to_char(W.DUE_DATE, 'J.SSSSS'), 'END_DATE', to_char(W.END_DATE, 'J.SSSSS'), 'STATUS', STATUS, 'FROMUSER', FROM_USER, 'RPRIORITY', to_char(1000000 - PRIORITY, '00000000'), to_char(PRIORITY, '00000000')); -- Delegate By Me cursor cursor wl_dbm_cursor(p0 pls_integer, p1 pls_integer) is select /*+ ORDERED INDEX (W.WN,WF_NOTIFICATIONS_N1) USE_NL (W.WN W.WIT W.WL) */ W.NID ,W.PRIORITY ,W.STATUS ,W.LANGUAGE ,W.MESSAGE_TYPE MESSAGE_TYPE ,W.RECIPIENT_ROLE RECIPIENT_ROLE ,W.SUBJECT SUBJECT ,to_char(W.BEGIN_DATE) BEGIN_DATE ,to_char(W.DUE_DATE) DUE_DATE ,to_char(W.END_DATE) END_DATE ,W.DISPLAY_STATUS DISPLAY_STATUS ,W.FROM_USER FROM_USER ,W.TO_USER TO_USER ,NA1.TEXT_VALUE from WF_WORKLIST_V W, WF_NOTIFICATION_ATTRIBUTES NA1 where W.NID = NA1.NOTIFICATION_ID (+) and NA1.NAME (+) = '#FROM_ROLE' and (username = '*' or (ORIGINAL_RECIPIENT in (select WUR.ROLE_NAME from WF_USER_ROLES WUR where WUR.USER_NAME = username) or ORIGINAL_RECIPIENT = username)) and RECIPIENT_ROLE <> ORIGINAL_RECIPIENT and (ldt = '*' or RECIPIENT_ROLE = upper(ldt)) and (littype = '*' or (ITEM_TYPE = littype)) and (lstatus is null or lstatus = '*' or (STATUS = lstatus)) and (lsubject = '*' or (SUBJECT like '%'||upper(lsubject)||'%')) and ((BEGIN_DATE is null and Worklist.lbeg_sent = '*' and Worklist.lend_sent = '*') or BEGIN_DATE between decode(Worklist.lbeg_sent, '*', BEGIN_DATE, to_date(Worklist.lbeg_sent)) and decode(Worklist.lend_sent, '*', BEGIN_DATE, to_date(Worklist.lend_sent)+1-(1/(24*60*60)))) and ((DUE_DATE is null and Worklist.lbeg_due = '*' and Worklist.lend_due = '*') or DUE_DATE between decode(Worklist.lbeg_due, '*', DUE_DATE, to_date(Worklist.lbeg_due)) and decode(Worklist.lend_due, '*', DUE_DATE, to_date(Worklist.lend_due)+1-(1/(24*60*60)))) and PRIORITY between p0 and p1 and (lfromuser = '*' or (NA1.TEXT_VALUE = lfromuser)) order by decode(upper(lorderkey), 'MESSAGE_TYPE', MESSAGE_TYPE, 'SUBJECT', SUBJECT, 'BEGIN_DATE', to_char(W.BEGIN_DATE, 'J.SSSSS'), 'DUE_DATE', to_char(W.DUE_DATE, 'J.SSSSS'), 'END_DATE', to_char(W.END_DATE, 'J.SSSSS'), 'STATUS', STATUS, 'FROMUSER', FROM_USER, 'RPRIORITY', to_char(1000000 - PRIORITY, '00000000'), to_char(PRIORITY, '00000000')); -- General worklist query cursor cursor wl_query_g_cursor (uname varchar2, uos varchar2, uosid number, p0 pls_integer, p1 pls_integer) is select /*+ ORDERED INDEX (W.WN,WF_NOTIFICATIONS_N1) USE_NL (W.WN W.WIT W.WL) */ W.NID ,W.PRIORITY ,W.STATUS ,W.LANGUAGE ,W.MESSAGE_TYPE MESSAGE_TYPE ,W.RECIPIENT_ROLE RECIPIENT_ROLE ,W.SUBJECT SUBJECT ,to_char(W.BEGIN_DATE) BEGIN_DATE ,to_char(W.DUE_DATE) DUE_DATE ,to_char(W.END_DATE) END_DATE ,W.DISPLAY_STATUS DISPLAY_STATUS ,W.FROM_USER FROM_USER ,W.TO_USER TO_USER ,NA1.TEXT_VALUE from WF_WORKLIST_V W, WF_NOTIFICATION_ATTRIBUTES NA1 where W.NID = NA1.NOTIFICATION_ID (+) and NA1.NAME (+) = '#FROM_ROLE' and (RECIPIENT_ROLE = uname or RECIPIENT_ROLE in (select WUR.ROLE_NAME from WF_USER_ROLES WUR where WUR.USER_ORIG_SYSTEM = uos and WUR.USER_ORIG_SYSTEM_ID = uosid and WUR.USER_NAME = uname)) and ITEM_TYPE = decode(Worklist.littype,'*',ITEM_TYPE, Worklist.littype) and (lstatus is null or lstatus = '*' or (STATUS = lstatus)) and (lsubject = '*' or (SUBJECT like '%'||upper(lsubject)||'%')) and ((BEGIN_DATE is null and Worklist.lbeg_sent = '*' and Worklist.lend_sent = '*') or BEGIN_DATE between decode(Worklist.lbeg_sent, '*', BEGIN_DATE, to_date(Worklist.lbeg_sent)) and decode(Worklist.lend_sent, '*', BEGIN_DATE, to_date(Worklist.lend_sent)+1-(1/(24*60*60)))) and ((DUE_DATE is null and Worklist.lbeg_due = '*' and Worklist.lend_due = '*') or DUE_DATE between decode(Worklist.lbeg_due, '*', DUE_DATE, to_date(Worklist.lbeg_due)) and decode(Worklist.lend_due, '*', DUE_DATE, to_date(Worklist.lend_due)+1-(1/(24*60*60)))) and PRIORITY between p0 and p1 and (lfromuser = '*' or (NA1.TEXT_VALUE = lfromuser)) order by decode(upper(lorderkey), 'MESSAGE_TYPE', MESSAGE_TYPE, 'SUBJECT', SUBJECT, 'BEGIN_DATE', to_char(W.BEGIN_DATE, 'J.SSSSS'), 'DUE_DATE', to_char(W.DUE_DATE, 'J.SSSSS'), 'END_DATE', to_char(W.END_DATE, 'J.SSSSS'), 'STATUS', STATUS, 'FROMUSER', FROM_USER, 'RPRIORITY', to_char(1000000 - PRIORITY, '00000000'), to_char(PRIORITY, '00000000')); role_info_tbl wf_directory.wf_local_roles_tbl_type; begin -- Check session and current user wfa_sec.GetSession(username); -- Get all the username find criteria resolved wfa_html.validate_display_name (display_owner, t_owner); wfa_html.validate_display_name (display_user, t_user); wfa_html.validate_display_name (display_fromuser, t_fromuser); wfa_html.validate_display_name (display_delegatedto, t_delegatedto); if (resetcookie = 0) then -- Look for a cookie with params from last call to Worklist. -- If current parameters were passed as null, then use the last settings -- from the cookie as defaults. begin if (fromlogin <> 0 ) then -- coming from apps login screen, force an exception -- so that cookie value is not being used raise invalid_cookie; end if; -- Retrieve cookie and extract value. -- If any possible error detected in the cookie, raise an exception to -- ignore the cookie and use the defaults instead. cookie := owa_cookie.get('WF_WORKLIST_MODE'); if (cookie.num_vals <> 1) then -- should not have any htp before owa_util.http_header_close raise bad_cookie; end if; -- Getting the cookie values -- ### I know it is a mess of code, we may think about cleaning this -- ### up some days -- c1 := instr(cookie.vals(1), ':'); c2 := instr(cookie.vals(1), ':', 1, 2); c3 := instr(cookie.vals(1), ':', 1, 3); c4 := instr(cookie.vals(1), ':', 1, 4); c5 := instr(cookie.vals(1), ':', 1, 5); c6 := instr(cookie.vals(1), ':', 1, 6); c7 := instr(cookie.vals(1), ':', 1, 7); c8 := instr(cookie.vals(1), ':', 1, 8); c9 := instr(cookie.vals(1), ':', 1, 9); c10 := instr(cookie.vals(1), ':', 1, 10); c11 := instr(cookie.vals(1), ':', 1, 11); c12 := instr(cookie.vals(1), ':', 1, 12); c13 := instr(cookie.vals(1), ':', 1, 13); c14 := instr(cookie.vals(1), ':', 1, 14); if ((c1 = 0) or (c2 = 0) or (c3 = 0) or (c4 = 0) or (c5 = 0) or (c6 = 0) or (c7 = 0) or (c8 = 0) or (c9 = 0) or (c10 = 0) or (c11= 0) or (c12= 0) or (c13= 0) or (c14= 0)) then raise bad_cookie; end if; -- -- Unless values are passed as argument, use the cookie values -- -- N.B. beware of the number/pls_integer type that we need conversion -- lorderkey := upper(nvl(orderkey, substr(cookie.vals(1), 1, c1-1))); lstatus := upper(nvl(status, substr(cookie.vals(1), c1+1, c2-c1-1))); luser := nvl(t_user, substr(cookie.vals(1), c2+1, c3-c2-1)); lowner := upper(nvl(t_owner,substr(cookie.vals(1), c3+1, c4-c3-1))); littype := nvl(ittype, substr(cookie.vals(1), c4+1, c5-c4-1)); lsubject := nvl(msubject, substr(cookie.vals(1), c5+1, c6-c5-1)); lbeg_sent := nvl(beg_sent, substr(cookie.vals(1), c6+1, c7-c6-1)); lend_sent := nvl(end_sent, substr(cookie.vals(1), c7+1, c8-c7-1)); lbeg_due := nvl(beg_due, substr(cookie.vals(1), c8+1, c9-c8-1)); lend_due := nvl(end_due, substr(cookie.vals(1), c9+1, c10-c9-1)); lpriority := nvl(priority, substr(cookie.vals(1), c10+1, c11-c10-1)); lnid := nvl(nid, to_number( substr(cookie.vals(1), c11+1, c12-c11-1))); ldt := nvl(t_delegatedto, substr(cookie.vals(1), c12+1, c13-c12-1)); ldbm := to_number(substr(cookie.vals(1), c13+1, c14-c13-1)); lfromuser := upper(nvl(t_fromuser,substr(cookie.vals(1), c14+1))); -- Check orderkey and status are valid. if (lorderkey not in ('PRIORITY', 'MESSAGE_TYPE', 'FROMUSER', 'TOUSER', 'SUBJECT', 'BEGIN_DATE', 'DUE_DATE', 'END_DATE', 'STATUS', 'RPRIORITY') or nvl(lstatus, '*') not in ('OPEN', 'CLOSED', 'CANCELED', 'ERROR', '*') ) then raise bad_cookie; end if; exception when others then -- Either not set or some error encountered. Use defaults. lorderkey := nvl(orderkey, 'PRIORITY'); lstatus := nvl(status, 'OPEN'); luser := nvl(t_user, username); lowner := '*'; littype := '*'; lsubject := '*'; lbeg_sent := '*'; lend_sent := '*'; lbeg_due := '*'; lend_due := '*'; lpriority := '*'; lnid := nvl(nid, -1); ldt := '*'; ldbm := 0; lfromuser := '*'; end; else -- -- When resetcookie is true, we don't set token values from -- the values in the cookie. -- For example, coming from "Find" screen, you do want to clear the -- value of lowner. -- On the other hand, you do want to preserve the value of ldbm when -- you sort the list of "delegated by me." -- lorderkey := nvl(orderkey, 'PRIORITY'); lstatus := nvl(status, 'OPEN'); luser := nvl(t_user, '*'); ldbm := delegated_by_me; lowner := upper(nvl(t_owner,'*')); littype := nvl(ittype, '*'); lsubject := nvl(msubject, '*'); lbeg_sent := nvl(beg_sent, '*'); lend_sent := nvl(end_sent, '*'); lbeg_due := nvl(beg_due, '*'); lend_due := nvl(end_due, '*'); lpriority := nvl(priority, '*'); ldt := nvl(t_delegatedto, '*'); lnid := nvl(nid, -1); lfromuser := nvl(t_fromuser, '*'); end if; /* ** Take care of the case where the item type has a space in it. ** We used a + to represent the space in the list of values since you ** can escape it in a poplist and pass it through the post. Here we'll ** switch it back and use it in the queries. */ littype := REPLACE(littype, '+', ' '); -- Send parameter values back to cookie. owa_util.mime_header('text/html', FALSE); owa_cookie.send('WF_WORKLIST_MODE', lorderkey||':'||lstatus||':'||luser ||':'||lowner||':'||littype||':'||lsubject||':'||lbeg_sent ||':'||lend_sent||':'||lbeg_due||':'||lend_due||':'||lpriority ||':'||lnid||':'||ldt||':'||ldbm||':'||lfromuser, '', '/'); owa_util.http_header_close; -- set the admin role admin_role := wf_core.translate('WF_ADMIN_ROLE'); -- set the username. This may get overwritten if performing a special query username := upper(username); -- Check whether current user has WF_ADMIN_ROLE privileges when: -- 1. Make a NID query -- 2. Specify owner in a query -- 3. Specify user other than himself in a query if (lnid >= 0 or lowner <> '*') then if (admin_role <> '*' and not Wf_Directory.IsPerformer(username, admin_role)) then isadmin := FALSE; Wf_Core.Token('UNAME', username); Wf_Core.Token('ROLE', admin_role); Wf_Core.Raise('WFMON_ADMIN_ROLE'); else isadmin := TRUE; end if; showothers := 1; end if; -- case 3 if (luser <> '*') then if (upper(luser) <> upper(username)) then if (admin_role <> '*' and not Wf_Directory.IsPerformer(username, admin_role)) then isadmin := FALSE; Wf_Core.Token('UNAME', username); Wf_Core.Token('ROLE', admin_role); Wf_Core.Raise('WFMON_ADMIN_ROLE'); end if; showothers := 1; username := luser; -- override the username field in this case. else showothers := 0; -- no need to show others when username is myself end if; isadmin := TRUE; end if; wf_directory.GetRoleInfo2(username, role_info_tbl); realname := role_info_tbl(1).display_name; -- In Regular User mode, if "Delegate by me", ldbm, is set, we will -- show To field, i.e., lshowto with value T. if ((ldbm > 0 and ldt = '*') or showothers = 1 ) then lshowto := 'T'; else lshowto := 'F'; end if; -- Set page title htp.htmlOpen; htp.headOpen; htp.title(wf_core.translate('WFA_WTITLE') || ' - ' || realname); wfa_html.create_help_function('wf/links/not.htm?NOTWORK'); if (instr(owa_util.get_cgi_env('HTTP_USER_AGENT'), 'MSIE') > 0) then htp.p(''); end if; htp.headClose; if worklist.clearbanner = 'TRUE' then wfa_sec.Header(background_only=>TRUE); else wfa_sec.Header(FALSE, owa_util.get_owa_service_path ||'wfa_html.Find', wf_core.translate('WFA_WTITLE'), TRUE); end if; -- debug info htp.p(''); htp.p(''); htp.p(''); -- Figure out the boundaries for priority if (GetPriorityBounds(lpriority, nf_p0, nf_p1) = FALSE) then wf_core.token('PRIORITY', lpriority); wf_core.raise('WFNTF_PRIORITY'); end if; outTab.DELETE; /* ### comment this out -- debug info if (isadmin) then htp.p(''); end if; htp.p(''); htp.p(''); htp.p(''); htp.p(''); htp.p(''); htp.p(''); htp.p(''); htp.p(''); htp.p(''); htp.p(''); htp.p(''); htp.p(''); htp.p(''); htp.p(''); ### comment the above out */ -- default cursor if (lorderkey='PRIORITY' and ldbm=0 and lowner='*' and littype='*' and lsubject='*' and lbeg_sent='*' and lend_sent='*' and lbeg_due='*' and lend_due='*' and lpriority='*' and ldt='*' and lnid=-1 and lstatus='OPEN' and lfromuser='*') then htp.p(''); htp.p(''); i := 0; /* JWSMITH BUG2232218 - Added if condition to check if username=role */ /* If so, then use wl_role_cursor instead of wl_def_cursor */ /* DLAM - Now wl_def_cursor should handle this as well usercolon := instr(username, ':'); if (usercolon<>0) then for rec in wl_role_cursor(username, role_info_tbl(1).orig_system, role_info_tbl(1).orig_system_id) loop i := i+1; outTab(i).nid := rec.nid; outTab(i).priority := rec.priority; outTab(i).status := rec.status; outTab(i).language := rec.language; outTab(i).col01 := rec.message_type; outTab(i).col02 := rec.recipient_role; outTab(i).col03 := rec.subject; outTab(i).col04 := rec.begin_date; outTab(i).col05 := rec.due_date; outTab(i).col06 := rec.end_date; outTab(i).col07 := rec.display_status; outTab(i).col08 := rec.from_user; outTab(i).col09 := rec.to_user; end loop; else */ for rec in wl_def_cursor(username, role_info_tbl(1).orig_system, role_info_tbl(1).orig_system_id) loop i := i+1; outTab(i).nid := rec.nid; outTab(i).priority := rec.priority; outTab(i).status := rec.status; outTab(i).language := rec.language; outTab(i).col01 := rec.message_type; outTab(i).col02 := rec.recipient_role; outTab(i).col03 := rec.subject; outTab(i).col04 := rec.begin_date; outTab(i).col05 := rec.due_date; outTab(i).col06 := rec.end_date; outTab(i).col07 := rec.display_status; outTab(i).col08 := rec.from_user; outTab(i).col09 := rec.to_user; end loop; -- end if; elsif (isadmin and lnid>0) then -- ### htp.p(''); htp.p(''); -- there should be one row only for nid query i := 1; for rec in wl_nid_cursor(lnid) loop outTab(i).nid := rec.nid; outTab(i).priority := rec.priority; outTab(i).status := rec.status; outTab(i).language := rec.language; outTab(i).col01 := rec.message_type; outTab(i).col02 := rec.recipient_role; outTab(i).col03 := rec.subject; outTab(i).col04 := rec.begin_date; outTab(i).col05 := rec.due_date; outTab(i).col06 := rec.end_date; outTab(i).col07 := rec.display_status; outTab(i).col08 := rec.from_user; outTab(i).col09 := rec.to_user; end loop; elsif (lorderkey<>'PRIORITY' and ldbm=0 and lowner='*' and littype='*' and lsubject='*' and lbeg_sent='*' and lend_sent='*' and lbeg_due='*' and lend_due='*' and lpriority='*' and ldt='*' and lnid=-1 and lstatus='OPEN' and lfromuser='*') then -- ### htp.p(''); htp.p(''); i := 0; for rec in wl_def_s_cursor(username, role_info_tbl(1).orig_system, role_info_tbl(1).orig_system_id) loop i := i+1; outTab(i).nid := rec.nid; outTab(i).priority := rec.priority; outTab(i).status := rec.status; outTab(i).language := rec.language; outTab(i).col01 := rec.message_type; outTab(i).col02 := rec.recipient_role; outTab(i).col03 := rec.subject; outTab(i).col04 := rec.begin_date; outTab(i).col05 := rec.due_date; outTab(i).col06 := rec.end_date; outTab(i).col07 := rec.display_status; outTab(i).col08 := rec.from_user; outTab(i).col09 := rec.to_user; end loop; -- default cursor elsif (lorderkey='PRIORITY' and ldbm=0 and lowner='*' and lsubject='*' and ldt='*' and lnid=-1 and lfromuser='*') then htp.p(''); htp.p(''); i := 0; for rec in wl_query_cursor(username, role_info_tbl(1).orig_system, role_info_tbl(1).orig_system_id, nf_p0, nf_p1) loop i := i+1; outTab(i).nid := rec.nid; outTab(i).priority := rec.priority; outTab(i).status := rec.status; outTab(i).language := rec.language; outTab(i).col01 := rec.message_type; outTab(i).col02 := rec.recipient_role; outTab(i).col03 := rec.subject; outTab(i).col04 := rec.begin_date; outTab(i).col05 := rec.due_date; outTab(i).col06 := rec.end_date; outTab(i).col07 := rec.display_status; outTab(i).col08 := rec.from_user; outTab(i).col09 := rec.to_user; end loop; elsif (isadmin) then htp.p(''); htp.p(''); i := 0; for rec in wl_admin_g_cursor(nf_p0, nf_p1) loop i := i+1; outTab(i).nid := rec.nid; outTab(i).priority := rec.priority; outTab(i).status := rec.status; outTab(i).language := rec.language; outTab(i).col01 := rec.message_type; outTab(i).col02 := rec.recipient_role; outTab(i).col03 := rec.subject; outTab(i).col04 := rec.begin_date; outTab(i).col05 := rec.due_date; outTab(i).col06 := rec.end_date; outTab(i).col07 := rec.display_status; outTab(i).col08 := rec.from_user; outTab(i).col09 := rec.to_user; end loop; elsif (ldbm <> 0) then htp.p(''); htp.p(''); i := 0; for rec in wl_dbm_cursor(nf_p0, nf_p1) loop i := i+1; outTab(i).nid := rec.nid; outTab(i).priority := rec.priority; outTab(i).status := rec.status; outTab(i).language := rec.language; outTab(i).col01 := rec.message_type; outTab(i).col02 := rec.recipient_role; outTab(i).col03 := rec.subject; outTab(i).col04 := rec.begin_date; outTab(i).col05 := rec.due_date; outTab(i).col06 := rec.end_date; outTab(i).col07 := rec.display_status; outTab(i).col08 := rec.from_user; outTab(i).col09 := rec.to_user; end loop; else htp.p(''); htp.p(''); i := 0; for rec in wl_query_g_cursor(username, role_info_tbl(1).orig_system, role_info_tbl(1).orig_system_id, nf_p0, nf_p1) loop i := i+1; outTab(i).nid := rec.nid; outTab(i).priority := rec.priority; outTab(i).status := rec.status; outTab(i).language := rec.language; outTab(i).col01 := rec.message_type; outTab(i).col02 := rec.recipient_role; outTab(i).col03 := rec.subject; outTab(i).col04 := rec.begin_date; outTab(i).col05 := rec.due_date; outTab(i).col06 := rec.end_date; outTab(i).col07 := rec.display_status; outTab(i).col08 := rec.from_user; outTab(i).col09 := rec.to_user; end loop; end if; -- If there are no notifications, display a message and exit if (outTab.COUNT = 0) then htp.tableopen(calign=>'CENTER', cattributes=>'summary=""'); htp.tablerowopen; if (fromfindscreen = 0) then htp.tabledata(cvalue=>wf_core.translate('WFA_NO_NOTIFY') || ' ' || realname || ' ('||username||').', cattributes=>'id="' || wf_core.translate('WFA_NO_NOTIFY') || '"'); else htp.tabledata(cvalue=>wf_core.translate('WFNTF_NO_MATCH'), cattributes=>'id="' || wf_core.translate('WFA_NO_MATCH') || '"'); end if; htp.tablerowclose; htp.tableclose; wfa_sec.Footer; htp.htmlClose; return; end if; -- Form begins htp.p(''); -- Hide the fields for which option you selected. Reassign vs Close htp.formHidden(cname=>'close', cvalue=>''); -- Hide the fields for which option you selected. Reassign vs Close htp.formHidden(cname=>'forward', cvalue=>''); -- There are some notifications for the user. Construct the page. htp.tableOpen('border=1 cellpadding=3 bgcolor=white width=100% summary=""'); -- Column headers htp.tableRowOpen(cattributes=>'bgcolor=#006699'); htp.tableHeader(cvalue=>''|| wf_core.translate('SELECT')||'', calign=>'Center', cattributes=>'id="' || WF_CORE.Translate('SELECT') || '"'); htp.tableHeader(cvalue=>htf.anchor(owa_util.get_owa_service_path|| 'wfa_html.worklist?orderkey=PRIORITY&clearbanner='||clearbanner, ''||wf_core.translate('PRIORITY')||'', null), calign=>'Center', cattributes=>'id="' || WF_CORE.Translate('PRIORITY') || '"'); htp.tableHeader(cvalue=>htf.anchor(owa_util.get_owa_service_path|| 'wfa_html.worklist?orderkey=MESSAGE_TYPE&clearbanner='||clearbanner, ''||wf_core.translate('TYPE')||'', null), calign=>'Center', cattributes=>'id="' || WF_CORE.Translate('TYPE') || '"'); htp.tableHeader(cvalue=>htf.anchor(owa_util.get_owa_service_path|| 'wfa_html.worklist?orderkey=FROMUSER&clearbanner='||clearbanner, ''||wf_core.translate('FROM')||'', null), calign=>'Center', cattributes=>'id="' || WF_CORE.Translate('FROM') || '"'); if (lshowto = 'T') then htp.tableHeader(cvalue=>htf.anchor(owa_util.get_owa_service_path|| 'wfa_html.worklist?orderkey=TOUSER&clearbanner='||clearbanner, ''||wf_core.translate('TO')||'', null), calign=>'Center', cattributes=>'id="' || WF_CORE.Translate('TO') || '"'); end if; htp.tableHeader(cvalue=>htf.anchor(owa_util.get_owa_service_path|| 'wfa_html.worklist?orderkey=SUBJECT&clearbanner='||clearbanner, ''||wf_core.translate('SUBJECT')||'', null), calign=>'Center', cattributes=>'id="' || WF_CORE.Translate('SUBJECT') || '"'); htp.tableHeader(cvalue=>htf.anchor(owa_util.get_owa_service_path|| 'wfa_html.worklist?orderkey=BEGIN_DATE&clearbanner='||clearbanner, ''||wf_core.translate('BEGIN_DATE')||'', null), calign=>'Center', cattributes=>'id="' || WF_CORE.Translate('BEGIN_DATE') || '"'); htp.tableHeader(cvalue=>htf.anchor( owa_util.get_owa_service_path|| 'wfa_html.worklist?orderkey=DUE_DATE&clearbanner='||clearbanner, ''||wf_core.translate('DUE_DATE')||'', null), calign=>'Center', cattributes=>'id="' || WF_CORE.Translate('DUE_DATE') || '"'); -- Add optional end date if querying closed/cancelled/invalid notifications if (nvl(lstatus,'x') <> 'OPEN') then htp.tableHeader(cvalue=>htf.anchor(owa_util.get_owa_service_path|| 'wfa_html.worklist?orderkey=END_DATE&clearbanner='||clearbanner, ''||wf_core.translate('END_DATE')||'', null), calign=>'Center', cattributes=>'id="' || WF_CORE.Translate('END_DATE') || '"'); end if; -- Add optional status if querying all notifications if (nvl(lstatus,'x') = '*') then htp.tableHeader(cvalue=>htf.anchor(owa_util.get_owa_service_path|| 'wfa_html.worklist?orderkey=STATUS&clearbanner='||clearbanner, ''||wf_core.translate('STATUS')||'', null), calign=>'Center', cattributes=>'id="' || WF_CORE.Translate('STATUS') || '"'); end if; htp.tableRowClose; htp.tableRowOpen; htp.tableRowClose; -- Hidden NIDS Field to handle the case when no notification id is selected htp.formHidden('NIDS', -1); -- Worklist for i in 1..outTab.COUNT loop -- Set the variables nf_nid := outTab(i).nid; nf_priority := outTab(i).priority; nf_status := outTab(i).status; nf_language := outTab(i).language; nf_message_type := outTab(i).col01; nf_recipient := outTab(i).col02; nf_subject := outTab(i).col03; nf_begin_date := outTab(i).col04; nf_due_date := outTab(i).col05; nf_end_date := outTab(i).col06; nf_display_status := outTab(i).col07; nf_from_user := outTab(i).col08; nf_to_user := outTab(i).col09; -- Check if we need to get denormalized value again if (nf_language is null or nf_language <> userenv('LANG')) then Wfa_Html_Util.GetDenormalizedValues(nf_nid, userenv('LANG'), nf_from_user, nf_to_user, nf_subject); end if; -- Figure out the priority first n_priority := GetPriorityIcon(nf_priority); -- Figure out whether response is required n_response := null; if (nf_status = 'OPEN') then open attrs(nf_nid); fetch attrs into result; if (attrs%found) then n_response := wfa_html.image_loc||'reqresp.gif'; end if; close attrs; end if; -- Displaying a row htp.tableRowOpen(null, 'TOP'); htp.tableData(htf.formCheckbox(cname=>'NIDS', cvalue=>nf_nid, cattributes=>'id="i_nids' || i || '"'), 'center', cattributes=>'id="' || WF_CORE.Translate('NOTIFICATION') || '"'); htp.p(''); htp.tableOpen('border=0 width="100%" summary=""'); htp.tableRowOpen(null,'TOP'); if (n_priority is null) then -- ### width below is ignored in html code, takes it out. -- ### htp.tableData('&'||'nbsp;', 'left', 'width="50%"'); htp.tableData('&'||'nbsp;', 'left', cattributes=>'id=""'); else htp.tableData(htf.img(curl=>n_priority, calt=>WFA_HTML.g_priority), 'center', cattributes=>'id="' || WFA_HTML.g_priority || '"'); end if; htp.tableRowClose; htp.tableClose; htp.p(''); htp.tableData(nf_message_type, 'left', cattributes=>'id=""'); htp.tableData(nvl(nf_from_user, ' '), 'left', cattributes=>'id=""'); if (lshowto = 'T') then htp.tableData(nf_to_user, 'left', cattributes=>'id=""'); end if; -- If response is required, append response required icon to subject if (n_response is null) then htp.tableData( cvalue=>'', calign=>'left'); else htp.tableData( cvalue=>'' || '&'||'nbsp;'||htf.img(curl=>n_response, calt=>WF_CORE.Translate('WFSRV_RECIPIENT_MUST_RESPOND')), calign=>'left'); end if; htp.tableData(cvalue=>nf_begin_date, calign=>'left', cnowrap=>1, cattributes=>'id=""'); htp.tableData(cvalue=>nvl(nf_due_date, '
'), calign=>'left', cnowrap=>1, cattributes=>'id=""'); -- Add optional end date if querying closed/cancelled/invalid notifications if (nvl(lstatus,'x') <> 'OPEN') then htp.tableData(cvalue=>nvl(nf_end_date, '
'), calign=>'left', cnowrap=>1, cattributes=>'id=""'); end if; -- Add optional status if querying all notifications if (nvl(lstatus,'x') = '*') then htp.tableData(nf_display_status, 'left', cattributes=>'id=""'); end if; htp.tableRowClose; end loop; htp.tableClose; htp.formHidden('showto', lshowto); htp.formClose; htp.tableopen (calign=>'CENTER', cattributes=>'summary=""'); htp.tableRowOpen; -- Close button htp.p(''); wfa_html.create_reg_button ('javascript:document.WFA_WORKLIST.close.value='|| ''''||'CLOSE'||''''|| ';document.WFA_WORKLIST.forward.value='|| ''''||''''|| ';document.WFA_WORKLIST.submit()', wf_core.translate ('CLOSE_MSG'), wfa_html.image_loc, '', wf_core.translate ('CLOSE')); htp.p(''); -- Reassign Button htp.p(''); wfa_html.create_reg_button ('javascript:document.WFA_WORKLIST.forward.value='|| ''''||'FORWARD'||''''|| ';document.WFA_WORKLIST.close.value='|| ''''||''''|| ';document.WFA_WORKLIST.submit()', wf_core.translate ('ASSIGN_MSG'), wfa_html.image_loc, '', wf_core.translate ('ASSIGN')); htp.p(''); htp.tableRowClose; htp.tableClose; htp.centerClose; wfa_sec.Footer; htp.htmlClose; exception when others then rollback; if (attrs%isopen) then close attrs; end if; wf_core.context('Wfa_Html','WorkList', orderkey, status, user); wfa_html.Error; end Worklist; -- -- Authenticate (PRIVATE) -- Verify user is allowed access to this notification -- IN -- nid - notification id -- nkey - notification access key (if disconnected) -- RETURNS -- Current user name -- function Authenticate( nid in number, nkey in varchar2) return varchar2 is usercolon pls_integer; rolecolon pls_integer; origcolon pls_integer; username varchar2(320); recipient varchar2(320); orig_recipient varchar2(320); dummy pls_integer; admin_role varchar2(320); slash pls_integer; wfsession varchar2(240); uos varchar2(320); uosid number; ros varchar2(320); rosid number; oos varchar2(320); oosid number; begin if (nkey is null) then -- No nkey passed, means must be connected. Get current user. Wfa_Sec.GetSession(username); -- Get recipient and original recipient of this notification begin select RECIPIENT_ROLE, ORIGINAL_RECIPIENT into recipient, orig_recipient from WF_NOTIFICATIONS WN where WN.NOTIFICATION_ID = nid; exception when no_data_found then Wf_Core.Token('NID', nid); Wf_Core.Raise('WFNTF_NID'); end; -- Verify this notification was sent to this user -- Note that username could be the in the recipient role -- or in the original recipient role. begin usercolon := instr(username, ':'); rolecolon := instr(recipient, ':'); origcolon := instr(orig_recipient, ':'); if (usercolon = 0) then -- very costly sql statement, return the first row we find. select ORIG_SYSTEM, ORIG_SYSTEM_ID into uos, uosid from WF_USERS where NAME = username and ORIG_SYSTEM not in ('HZ_PARTY','CUST_CONT') and rownum < 2; else uos := substr(username, 1, usercolon-1); uosid := to_number(substr(username, usercolon+1)); end if; if (rolecolon = 0) then -- when recipient = username, user is participate in the role of -- the same name, they will have the same orig system and orig -- system id. if (recipient = username) then ros := uos; rosid := uosid; else Wf_Directory.GetRoleOrigSysInfo(recipient,ros,rosid); end if; else ros := substr(recipient, 1, rolecolon-1); rosid := to_number(substr(recipient, rolecolon+1)); end if; if (origcolon = 0) then -- similarly, don't bother to requery the orig_system and -- orig_system_id if original recipient matches recipient or username. if (orig_recipient = recipient) then oos := ros; oosid := rosid; elsif (orig_recipient = username) then oos := uos; oosid := uosid; else Wf_Directory.GetRoleOrigSysInfo(orig_recipient,oos,oosid); end if; else oos := substr(orig_recipient, 1, origcolon-1); oosid := to_number(substr(orig_recipient, origcolon+1)); end if; -- rewritten the sql from an or join to union all. -- reduced the query time from >25 sec to <0.5 sec. select 1 into dummy from sys.dual where exists ( select null from WF_USER_ROLES where USER_ORIG_SYSTEM = uos and USER_ORIG_SYSTEM_ID = uosid and USER_NAME = username and ROLE_ORIG_SYSTEM = ros and ROLE_ORIG_SYSTEM_ID = rosid and ROLE_NAME = recipient union all select null from WF_USER_ROLES where USER_ORIG_SYSTEM = uos and USER_ORIG_SYSTEM_ID = uosid and USER_NAME = username and ROLE_ORIG_SYSTEM = oos and ROLE_ORIG_SYSTEM_ID = oosid and ROLE_NAME = orig_recipient ); exception when no_data_found then -- Check if current user has WF_ADMIN_ROLE privileges. -- If so, allow access anyway. admin_role := wf_core.translate('WF_ADMIN_ROLE'); if (admin_role <> '*' and not Wf_Directory.IsPerformer(username, admin_role)) then Wf_Core.Token('USER', username); Wf_Core.Token('NID', to_char(nid)); Wf_Core.Raise('WFNTF_ACCESS_USER'); end if; end; else -- Nkey passed, means this must be disconnected (mailed html). -- Check the passed access key against the notification key. -- Construct wfsession-style access key as /. -- First strip from nkey if present (only for backward -- compatibility, current version only passes ), -- then construct full key with current nid. -- Note: Key is reconstructed here instead of passing full -- / directly to check that the key being passed -- is really for this notification. slash := instr(nkey, '/'); if (slash <> 0) then wfsession := to_char(nid)||'/'||substr(nkey, slash+1); else wfsession := to_char(nid)||'/'||nkey; end if; username := Wf_Notification.AccessCheck(wfsession); if (username is null) then wf_core.raise('WFNTF_ACCESS_KEY'); end if; end if; return(username); exception when others then wf_core.context('Wfa_Html', 'Authenticate', to_char(nid), nkey); raise; end Authenticate; -- -- DetailFrame -- generate Detail notification screen -- IN -- nid - notification id -- nkey - notification access key (for mailed html only) -- agent - web agent (OBSOLETE - for back compatibility only) -- showforms - show form attributes -- procedure DetailFrame( nid in varchar2, nkey in varchar2, agent in varchar2, showforms in varchar2) as slash pls_integer; col pls_integer; first_doc boolean := TRUE; wfsession varchar2(240); link_name varchar2(240); username varchar2(320); disprole varchar2(320); titlerole varchar2(320); s0 varchar2(2000); link_text varchar2(2000); comment_title varchar2(2000); l_document_attributes fnd_document_management.fnd_document_attributes; l_status boolean := FALSE; cnt pls_integer := 0; end_of_text boolean :=FALSE; msgbody varchar2(32000); pseudo_login boolean := FALSE; sess_username varchar2(320); l_subject varchar2(2000); l_forms_port varchar2(120); -- Select notification info cursor notcurs is select WN.STATUS, WN.RECIPIENT_ROLE, WN.ORIGINAL_RECIPIENT, WN.PRIORITY, WN.BEGIN_DATE, WN.DUE_DATE, WN.END_DATE, WIT.DISPLAY_NAME message_type, WL.MEANING disp_status, WN.USER_COMMENT, WN.FROM_USER, WN.TO_USER, WN.SUBJECT, WN.LANGUAGE from WF_NOTIFICATIONS WN, WF_ITEM_TYPES_VL WIT, WF_LOOKUPS WL where WN.NOTIFICATION_ID = to_number(nid) and WN.MESSAGE_TYPE = WIT.NAME and WL.LOOKUP_TYPE = 'WF_NOTIFICATION_STATUS' and WN.STATUS = WL.LOOKUP_CODE; notrec notcurs%rowtype; -- Select attr values, formatting numbers and dates as requested. -- The order-by is to handle cases where one attr name is a substring -- of another. cursor notification_attrs_cursor(nid number) is select WNA.NAME, WMA.TYPE, WMA.FORMAT, WMA.DISPLAY_NAME, WNA.TEXT_VALUE from WF_NOTIFICATION_ATTRIBUTES WNA, WF_NOTIFICATIONS WN, WF_MESSAGE_ATTRIBUTES_VL WMA where WNA.NOTIFICATION_ID = nid and WN.NOTIFICATION_ID = WNA.NOTIFICATION_ID and WN.MESSAGE_TYPE = WMA.MESSAGE_TYPE and WN.MESSAGE_NAME = WMA.MESSAGE_NAME and WMA.NAME = WNA.NAME and WMA.TYPE IN ('DOCUMENT', 'URL') and WMA.ATTACH = 'Y' and WNA.TEXT_VALUE IS NOT NULL and WMA.SUBTYPE = 'SEND' order by length(WNA.NAME) desc; -- similar to the above except FORMS do not set ATTACH to Y cursor ntf_forms_attrs_cursor(nid number) is select WNA.NAME, WMA.TYPE, WMA.FORMAT, WMA.DISPLAY_NAME, WNA.TEXT_VALUE from WF_NOTIFICATION_ATTRIBUTES WNA, WF_NOTIFICATIONS WN, WF_MESSAGE_ATTRIBUTES_VL WMA where WNA.NOTIFICATION_ID = nid and WN.NOTIFICATION_ID = WNA.NOTIFICATION_ID and WN.MESSAGE_TYPE = WMA.MESSAGE_TYPE and WN.MESSAGE_NAME = WMA.MESSAGE_NAME and WMA.NAME = WNA.NAME and WMA.TYPE = 'FORM' and WNA.TEXT_VALUE IS NOT NULL and WMA.SUBTYPE = 'SEND' order by length(WNA.NAME) desc; begin -- Authenticate user username := Wfa_Html.Authenticate(to_number(nid), nkey); if (nkey is not null) then -- Set a cookie for future IC access. -- Construct wfsession-style access key as /. -- First strip from nkey if present (only for backward -- compatibility, current version only passes ), -- then construct full key with current nid. -- Note: Key is reconstructed here instead of passing full -- / directly to check that the key being passed -- is really for this notification. slash := instr(nkey, '/'); if (slash <> 0) then wfsession := nid||'/'||substr(nkey, slash+1); else wfsession := nid||'/'||nkey; end if; /* ** Create the ICX psuedo session so ICX does not recreate the psuedo ** session. ** But first check to see if there is a current session */ begin wfa_sec.validate_only := TRUE; wfa_sec.GetSession(sess_username); if (sess_username <> 'ANONYMOUS' and sess_username <> '-1' and sess_username is not null) then -- there is a valid session already, just use it username := sess_username; else -- username -1 meant user had logged out. Do this to reset the page. if (sess_username = '-1') then owa_util.showpage; end if; -- create a pseudo session for user owa_util.mime_header('text/html', FALSE); owa_cookie.send('WF_SESSION', wfsession, '', '/'); wfa_sec.PseudoSession(FALSE, username); owa_util.http_header_close; end if; exception when OTHERS then -- this is the first attempt to see a detached notfication wf_core.clear; owa_util.mime_header('text/html', FALSE); owa_cookie.send('WF_SESSION', wfsession, '', '/'); wfa_sec.PseudoSession(FALSE, username); owa_util.http_header_close; end; wfa_sec.validate_only := FALSE; pseudo_login := TRUE; end if; -- Get notification info open notcurs; fetch notcurs into notrec; if (notcurs%notfound) then close notcurs; wf_core.token('NID', nid); wf_core.raise('WFNTF_NID'); end if; close notcurs; if (notrec.language = userenv('LANG')) then disprole := notrec.to_user; l_subject := notrec.subject; else Wf_Directory.GetRoleInfo(notrec.recipient_role, disprole, s0, s0, s0, s0); l_subject := Wf_Notification.GetSubject(to_number(nid)); end if; titlerole := disprole; -- -- Header and Page Title -- htp.htmlOpen; htp.headOpen; fnd_document_management.get_open_dm_display_window; if (notrec.status = 'OPEN') then htp.title(wf_core.translate('WFA_DTITLE')||' '||titlerole); else htp.title(wf_core.translate('WFA_CDTITLE')||' '||titlerole); end if; wfa_html.create_help_function('wf/links/det.htm?DETNOT'); -- Make sure the resulting link puts on the top window. htp.p(''); htp.headClose; htp.p(''); htp.p(''); htp.p(''); htp.p(''); htp.p(''); htp.p(''); if (nkey is null) then wfa_sec.Header(FALSE, owa_util.get_owa_service_path ||'wfa_html.Find', wf_core.translate('WFA_DTITLE_TBAR'), FALSE, pseudo_login); else -- disabled Find for detached notification wfa_sec.Header(FALSE, null, wf_core.translate('WFA_DTITLE_TBAR'), FALSE, pseudo_login); end if; htp.tableOpen(cattributes=>'WIDTH=100% summary=""', calign=>'CENTER'); -- -- LINE 0: from user if it is not null -- if (notrec.from_user is not null) then htp.tableRowOpen(cvalign=>'Baseline'); htp.tableData(cvalue=>wf_core.translate('FROM'), calign=>'right', cattributes=>'id=""'); htp.tableHeader(cvalue=>notrec.from_user, cnowrap=>1, calign=>'left', cattributes=>'BGCOLOR=WHITE WIDTH="*" id=""'); htp.tableRowClose; end if; -- -- LINE 1: (begin_date -> end_date) -- htp.tableRowOpen(cvalign=>'Baseline'); -- Always print Sent To and begin_date htp.tableData(cvalue=>wf_core.translate('TO'), calign=>'right', cattributes=>'id=""'); htp.tableHeader(cvalue=>disprole, cnowrap=>1, calign=>'left', cattributes=>'BGCOLOR=WHITE WIDTH="*" id=""'); htp.tableData(cvalue=>wf_core.translate('BEGIN_DATE'), calign=>'right', cattributes=>'id=""'); htp.tableHeader(cvalue=>to_char(notrec.begin_date)|| to_char(notrec.begin_date, ' HH24:MI:SS'), cnowrap=>1, calign=>'left', cattributes=>'BGCOLOR=WHITE WIDTH="25%" id=""'); -- keep track of columns in first row of table col := 4; -- Due: -- Do not print Due Date if it is null if (to_char(notrec.due_date) is not null) then htp.tableData(cvalue=>wf_core.translate('DUE_DATE'), calign=>'right', cattributes=>'id=""'); htp.tableHeader(cvalue=>to_char(notrec.due_date)|| to_char(notrec.due_date, ' HH24:MI:SS'), cnowrap=>1, calign=>'left', cattributes=>'BGCOLOR=WHITE WIDTH="25%" id=""'); col := col+2; end if; -- Closed: (only if not open) if (notrec.status <> 'OPEN') then if (notrec.status = 'CANCELED') then htp.tableData(cvalue=>wf_core.translate('CANCELED'), calign=>'right', cattributes=>'id=""'); else htp.tableData(cvalue=>wf_core.translate('END_DATE'), calign=>'right', cattributes=>'id=""'); end if; htp.tableHeader(cvalue=>to_char(notrec.end_date)|| to_char(notrec.end_date, ' HH24:MI:SS'), cnowrap=>1, calign=>'left', cattributes=>'BGCOLOR=WHITE WIDTH="25%" id=""'); col := col+2; end if; htp.tableRowClose; -- -- Subject: -- htp.tableRowOpen(cvalign=>'Baseline'); htp.tableData(cvalue=>wf_core.translate('SUBJECT'), calign=>'right', cattributes=>'id=""'); --make colspan 1 less than col because 1 col is taken up by "subject" htp.tableHeader(cvalue=>l_subject, calign=>'left', ccolspan=>col-1, cattributes=>'BGCOLOR=WHITE id=""'); htp.tableRowClose; htp.tableClose; -- -- COMMENTS -- if (notrec.user_comment is not null) then htp.p(wf_core.translate('COMMENTS')||':'); htp.tableOpen(cattributes=>'WIDTH=100% BGCOLOR=WHITE summary=""'); htp.tableRowOpen; htp.p(''); htp.bold(replace(notrec.user_comment, wf_core.newline, htf.br||wf_core.newline)); htp.p(''); htp.tableRowClose; htp.tableClose; end if; -- -- BODY -- htp.hr; htp.tableOpen(cattributes=>'WIDTH=100% BGCOLOR=WHITE summary=""'); htp.tableRowOpen; end_of_text:=FALSE; -- print message body. This may be in sections. htp.p(''); while not (end_of_text) loop wf_notification.getfullbody(to_number(nid),msgbody,end_of_text, wf_notification.doc_html); htp.prn(msgbody); end loop; htp.p(''); htp.tableRowClose; htp.tableClose; htp.br; for not_attr_row in notification_attrs_cursor(nid) loop if (first_doc = TRUE) then htp.hr; htp.br; htp.tableopen(cattributes=>'BORDER=0 cellpadding=0 cellspacing=0 summary=""'); htp.tablerowopen; first_doc := FALSE; end if; if (not_attr_row.type = 'DOCUMENT') then if (UPPER(SUBSTR(not_attr_row.text_value, 1, 2)) = 'DM') then /* ** Get the HTML text for displaying the document */ fnd_document_management.get_launch_document_url ( username, not_attr_row.text_value, FALSE, link_text); link_text := ''|| '' ||
                 WF_CORE.Translate('WFITD_ATTR_TYPE_DOCUMENT') || ''; elsif (UPPER(SUBSTR(not_attr_row.text_value, 1, 5)) = 'PLSQL') then if (nkey is null) then link_text := ''|| '' ||
                 WF_CORE.Translate('WFITD_ATTR_TYPE_DOCUMENT') || ''; else link_text := ''|| '' ||
                 WF_CORE.Translate('WFITD_ATTR_TYPE_DOCUMENT') || ''; end if; end if; elsif (not_attr_row.type = 'URL') then link_text := wf_notification.geturltext(not_attr_row.text_value, nid); --### debug htp.p(''); htp.p(''); link_text := wf_notification.SetFrameworkAgent(link_text); htp.p(''); link_text := ''|| '' ||
                 WF_CORE.Translate('WFITD_ATTR_TYPE_DOCUMENT') || ''; end if; htp.tabledata(cvalue=>link_text, calign=>'CENTER', cattributes=>'id=""'); htp.tabledata(cvalue=>'   ', calign=>'CENTER', cattributes=>'id=""'); end loop; if (showforms is not null) then for not_attr_row in ntf_forms_attrs_cursor(nid) loop if (first_doc = TRUE) then htp.hr; htp.br; htp.tableopen(cattributes=>'BORDER=0 cellpadding=0 cellspacing=0 summary=""'); htp.tablerowopen; first_doc := FALSE; end if; --Check the SOCKET_LISTENER_PORT profile option. l_forms_port := Wfa_Sec.Get_Profile_Value('SOCKET_LISTENER_PORT',username); htp.p(''); Wf_Forms.Applet( fname=>Wf_Notification.GetShortText(not_attr_row.text_value, nid), status=>l_status, dispname=>not_attr_row.display_name, port=>nvl(l_forms_port, '0')); htp.p(''); htp.tabledata(cvalue=>'   ', calign=>'CENTER', cattributes=>'id=""'); if (not l_status) then cnt := cnt + 1; end if; end loop; end if; -- If you found a row then close the table row you opened and open a new -- one for the document title if (first_doc = FALSE) then htp.tableRowClose; htp.tablerowopen; end if; for not_attr_row in notification_attrs_cursor(nid) loop if (not_attr_row.type = 'DOCUMENT') then if (UPPER(SUBSTR(not_attr_row.text_value, 1, 2)) = 'DM') then /* ** Get the HTML text for displaying the document */ fnd_document_management.get_launch_document_url ( username, not_attr_row.text_value, FALSE, link_text); link_text := ''|| not_attr_row.display_name|| ''; elsif (UPPER(SUBSTR(not_attr_row.text_value, 1, 5)) = 'PLSQL') then if (nkey is null) then link_text := ''|| not_attr_row.display_name||''; else link_text := ''|| not_attr_row.display_name||''; end if; end if; elsif (not_attr_row.type = 'URL') then link_text := wf_notification.geturltext(not_attr_row.text_value, nid); link_text := wf_notification.SetFrameworkAgent(link_text); link_text := ''|| not_attr_row.display_name||''; end if; htp.tabledata(cvalue=>link_text, calign=>'CENTER', cattributes=>'id=""'); htp.tabledata(cvalue=>'   ', calign=>'CENTER', cattributes=>'id=""'); end loop; if (showforms is not null) then for not_attr_row in ntf_forms_attrs_cursor(nid) loop htp.p(''); htp.p(not_attr_row.display_name); htp.p(''); htp.tabledata(cvalue=>'   ', calign=>'CENTER', cattributes=>'id=""'); end loop; end if; -- If you found a row then close the table row you opened and open a new -- one for the document title if (first_doc = FALSE) then htp.tableRowClose; htp.tableClose; end if; -- -- Print warning message -- if (cnt > 0) then htp.p('

'||wf_core.translate('WF_EXECUTE_FORM_FAILED')); htp.br; end if; -- -- Page footer -- Wfa_Sec.Footer; htp.htmlClose; exception when others then rollback; wf_core.context('Wfa_Html', 'DetailFrame', nid, nkey); wfa_html.Error; end DetailFrame; -- -- ResponseFrame -- generate response frame contents -- IN -- nid - notification id -- nkey - notification access key (for mailed html only) -- agent - web agent (OBSOLETE - for back compatibility only) -- showforms - show form attributes -- procedure ResponseFrame( nid in varchar2, nkey in varchar2, agent in varchar2, showforms in varchar2) as username varchar2(320); recipient varchar2(320); realname varchar2(360); status varchar2(8); s0 varchar2(2000); -- url_str varchar2(240); l_status boolean := FALSE; cnt pls_integer := 0; pseudo_login boolean := FALSE; l_forms_port varchar2(120); cursor attrs(resultflag in varchar2, typeflag in varchar2) is select MA.NAME, MA.DISPLAY_NAME, MA.DESCRIPTION, -- remove quotes for onmouse over java func replace(MA.DESCRIPTION,'''') description2, NA.TEXT_VALUE, NA.NUMBER_VALUE, NA.DATE_VALUE, MA.TYPE, MA.FORMAT from WF_NOTIFICATION_ATTRIBUTES NA, WF_MESSAGE_ATTRIBUTES_VL MA, WF_NOTIFICATIONS N where N.NOTIFICATION_ID = to_number(ResponseFrame.nid) and NA.NOTIFICATION_ID = N.NOTIFICATION_ID and MA.MESSAGE_NAME = N.MESSAGE_NAME and MA.MESSAGE_TYPE = N.MESSAGE_TYPE and MA.NAME = NA.NAME and MA.SUBTYPE = 'RESPOND' and MA.TYPE <> 'FORM' and ((resultflag = 'RESULT' and MA.NAME = 'RESULT') or (resultflag <> 'RESULT' and MA.NAME <> 'RESULT')) and MA.TYPE = decode(typeflag, '', MA.TYPE, typeflag) order by MA.SEQUENCE; cursor forms_attrs is select MA.NAME, MA.DISPLAY_NAME, MA.DESCRIPTION, -- remove quotes for onmouse over java func replace(MA.DESCRIPTION,'''') description2, NA.TEXT_VALUE from WF_NOTIFICATION_ATTRIBUTES NA, WF_MESSAGE_ATTRIBUTES_VL MA, WF_NOTIFICATIONS N where N.NOTIFICATION_ID = to_number(ResponseFrame.nid) and NA.NOTIFICATION_ID = N.NOTIFICATION_ID and MA.MESSAGE_NAME = N.MESSAGE_NAME and MA.MESSAGE_TYPE = N.MESSAGE_TYPE and MA.NAME = NA.NAME and MA.SUBTYPE = 'RESPOND' and MA.TYPE = 'FORM' order by MA.SEQUENCE; result attrs%rowtype; dvalue varchar2(2000); respcnt pls_integer; urlcount pls_integer; urlstring varchar2(4000); result_count pls_integer; resp_lbl varchar2(80); colon pls_integer; dmstype varchar2(30) := ''; document varchar2(32000) := ''; hide_button varchar2(1); sess_username varchar2(320); begin -- Authenticate user username := Wfa_Html.Authenticate(to_number(nid), nkey); Wf_Notification.GetInfo(to_number(nid), recipient, s0, s0, s0, s0, status); Wf_Directory.GetRoleInfo(recipient, realname, s0, s0, s0, s0); -- if nkey is not null, it is from email, and we need to create a pseudo -- session for it. if (nkey is not null) then begin wfa_sec.validate_only := TRUE; wfa_sec.GetSession(sess_username); if (sess_username <> 'ANONYMOUS' and sess_username <> '-1' and sess_username is not null) then -- there is a valid session already, just use it username := sess_username; else -- username -1 meant user had logged out. Do this to reset the page. if (sess_username = '-1') then owa_util.showpage; end if; -- create a pseudo session for user owa_util.mime_header('text/html', FALSE); wfa_sec.PseudoSession(FALSE, username); end if; exception when OTHERS then -- this is the first attempt to see a detached notfication wf_core.clear; owa_util.mime_header('text/html', FALSE); wfa_sec.PseudoSession(FALSE, username); end; wfa_sec.validate_only := FALSE; end if; wfa_html_util.GetUrlCount(to_number(nid),urlcount,urlstring); -- If there is just one url then replace the response frame with the url if (urlcount = 1) then -- GoToUrl(wf_notification.GetURLText(urlstring, nid),'_self'); owa_util.redirect_url(wf_notification.GetURLText(urlstring, nid)); return; end if; -- bug 2167012 JWSMITH moved header_close to after owa_util.redirect owa_util.http_header_close; -- -- Header and Page Title -- htp.htmlOpen; htp.headOpen; if (status = 'OPEN') then htp.title(wf_core.translate('WFA_DTITLE')||' '||realname); else htp.title(wf_core.translate('WFA_CDTITLE')||' '||realname); end if; -- Add the java script to the header to open the dm window for -- any DM function that is executed. fnd_document_management.get_open_dm_attach_window; fnd_document_management.get_open_dm_display_window; htp.headClose; htp.p(''); htp.p(''); htp.p(''); htp.p(''); htp.p(''); htp.p(''); -- -- Response body content -- wfa_sec.header(background_only=>TRUE); -- Add the Return to Worklist link before other attributes. -- We shows it regardless if we have open response or not. -- Fix bug #785206. We don't show the WorkList link if is coming from -- email attachment if (nkey is null) then htp.center(htf.anchor( curl => owa_util.get_owa_service_path||'wfa_html.WorkList', ctext => wf_core.translate('WFA_WORKLIST_RETURN'), cattributes=>'TARGET="_top"')); else pseudo_login := TRUE; end if; -- -- Handle Response Forms Attributes -- Note that similar to URL, it is mutally exclusive to other attributes -- -- Do not allow any response if notification is not opened -- if (status = 'OPEN') then if (showforms is not null) then htp.tableOpen(cattributes=>'summary=""'); respcnt := 0; for rec in forms_attrs loop htp.tableRowOpen; htp.p(''); if (rec.description is not null) then htp.p(rec.description); else htp.br; end if; htp.p(''); --Check the SOCKET_LISTENER_PORT profile option. l_forms_port := Wfa_Sec.Get_Profile_Value('SOCKET_LISTENER_PORT',username); htp.p(''); Wf_Forms.Applet(fname=>Wf_Notification.GetShortText(rec.text_value, to_number(ResponseFrame.nid)), status=>l_status, port=>nvl(l_forms_port, '0')); htp.p(''); htp.tableRowClose; htp.tableRowOpen; htp.tableData(rec.display_name, 'CENTER', cattributes=>'id=""'); htp.tableRowClose; if (not l_status) then cnt := cnt + 1; end if; respcnt := respcnt + 1; end loop; htp.tableClose; -- -- Print warning message -- if (cnt > 0) then htp.p('

'||wf_core.translate('WF_EXECUTE_FORM_FAILED')); htp.br; end if; if (respcnt >= 1) then Wfa_Sec.Footer; htp.htmlClose; return; end if; end if; end if; -- -- Check for response URLs. If more than one is found, display a list of -- URL links instead of the standard response frame. If only one is found -- then the main response frame function will be replaced in the detail -- procedure -- if (urlcount > 1) then htp.tableOpen(cattributes=>'summary=""'); for rec in attrs('NORESULT', 'URL') loop htp.tableRowOpen; wfa_html_util.GetUrl(nid, rec.description, rec.text_value); htp.tableRowClose; end loop; htp.tableClose; Wfa_Sec.Footer; htp.htmlClose; return; end if; if (status = 'OPEN') then htp.p(''); htp.formHidden('nkey', nkey); htp.formHidden('forward', null); -- Add dummy fields to start both array-type input fields. -- These dummy values are needed so that the array parameters to -- the submit procedure will not be null even if there are no real -- response fields. This would cause a pl/sql error, because array -- parameters can't be defaulted. htp.formHidden('h_fnames', 'Dummy_Name'); htp.formHidden('h_fvalues', 'Dummy_Value'); htp.formHidden('h_fdocnames', 'Dummy_Value'); else -- Add submitted title if ntf not open if (status = 'CANCELED') then htp.center(htf.bold(wf_core.translate('WFA_NOTIF_CANCELED'))); else if (pseudo_login) then htp.center(htf.bold(wf_core.translate('WFA_RESPONSE_COMPLETE'))); else htp.center(htf.bold(wf_core.translate('WFA_SUBMIT_RESPONSE'))); end if; end if; end if; -- -- Non-RESULT Response attribute fields -- Add a field for every non-result response attribute -- htp.tableOpen(cattributes=>'summary=""'); respcnt := 0; for rec in attrs('NORESULT', '') loop htp.tableRowOpen; -- Draw prompt with anchor for info htp.tableData( cvalue=>htf.anchor( curl=>owa_util.get_owa_service_path|| 'wfa_html.AttributeInfo?nid='||nid|| '&'||'name='||rec.name, ctext=>rec.display_name, cattributes=>'OnMouseOver="window.status='''||wfa_html.replace_onMouseOver_quotes(rec.description2)||'''; return true"'), calign=>'right', cattributes=>'id=""'); dvalue := wfa_html_util.GetDisplayValue(rec.type, rec.format, rec.text_value, rec.number_value, rec.date_value); if (status <> 'OPEN') then if (rec.type = 'DOCUMENT' and dvalue is not null) then -- Parse doc mgmt system type from dvalue colon := instr(dvalue, ':'); if ((colon <> 0) and (colon < 30)) then dmstype := upper(substr(dvalue, 1, colon-1)); end if; if (dmstype = 'DM') then /* ** Get the HTML text for displaying the document */ fnd_document_management.get_launch_document_url ( username, dvalue, FALSE, document); document := ''||rec.display_name|| ''; -- If ntf not open print displayed value as boilerplate -- instead of fields. htp.tableData(cvalue=>document, cattributes=>'BGCOLOR=WHITE id=""'); elsif (dmstype = 'PLSQL') then -- If ntf not open print displayed value as boilerplate -- instead of fields. htp.tableData(cvalue=>dvalue, cattributes=>'BGCOLOR=WHITE id=""'); end if; else -- If ntf not open print displayed value as boilerplate -- instead of fields. htp.tableData(cvalue=>dvalue, cattributes=>'BGCOLOR=WHITE id=""'); end if; else respcnt := respcnt + 1; if (rec.type = 'LOOKUP') then wfa_html_util.GetLookup(rec.name, rec.text_value, rec.format, FALSE); else if (nkey is null) then wfa_html_util.GetField(rec.name,rec.type,rec.format,dvalue,respcnt); else wfa_html_util.GetField(rec.name,rec.type,rec.format,dvalue,respcnt, to_number(nid), nkey); end if; end if; end if; htp.tableRowClose; end loop; -- -- RESULT attribute -- Add result attribute to bottom of page -- open attrs('RESULT', ''); fetch attrs into result; if (attrs%notfound) then -- No result if (status = 'OPEN') then if (respcnt > 0) then -- Non-result responses exist. -- Add a 'Submit' button to submit the form. htp.tableRowOpen; htp.p(''); wfa_html.create_reg_button ('javascript:document.WFNOTRESP.submit()', wf_core.translate ('SUBMIT'), wfa_html.image_loc, null, wf_core.translate ('SUBMIT')); htp.p(''); else -- No responses at all. -- Add a message to that effect. htp.tableRowOpen; htp.tableData(wf_core.translate('WFA_NO_RESPONSE'), cattributes=>'id=""'); htp.tableRowClose; -- Followed by a 'Close' button htp.tableRowOpen; htp.p(''); htp.tableopen(cattributes=>'summary=""'); htp.tablerowopen; htp.p(''); wfa_html.create_reg_button ('javascript:document.WFNOTRESP.submit()', wf_core.translate ('CLOSE'), wfa_html.image_loc, null, wf_core.translate ('CLOSE')); htp.p(''); end if; end if; else -- Result found -- Draw prompt with anchor for info htp.tableRowOpen; htp.tableData( cvalue=>htf.anchor( curl=>owa_util.get_owa_service_path|| 'wfa_html.AttributeInfo?nid='||nid|| '&'||'name=RESULT', ctext=>result.display_name, cattributes=>'OnMouseOver="window.status='''||wfa_html.replace_onMouseOver_quotes(result.description2)||'''; return true"'), calign=>'right', cattributes=>'id=""'); if (status = 'OPEN') then -- Draw response buttons htp.p(''); htp.tableopen(cattributes=>'cellspacing=0 summary=""'); htp.tablerowopen; respcnt := respcnt + 1; wfa_html_util.GetButtons(result.text_value, result.format, respcnt); else -- Not open. Throw the result into boilerplate. htp.tableData(cvalue=>wfa_html_util.GetDisplayValue(result.type, result.format, result.text_value, result.number_value, result.date_value), cattributes=>'BGCOLOR=WHITE id=""'); end if; end if; close attrs; -- Add forward button if still open if (status = 'OPEN') then -- Hide the Reassign button if a hidden attribute #HIDE_REASSIGN -- is set to Y. -- Exception handling is needed in case this attribute is not set. hide_button := 'N'; begin hide_button := Wf_Notification.GetAttrText(nid, '#HIDE_REASSIGN'); exception when OTHERS then -- Do not want anything on the error stack Wf_Core.Clear; end; if (hide_button <> 'Y') then htp.p(''); wfa_html.create_reg_button ('javascript:document.WFNOTRESP.forward.value=1; document.WFNOTRESP.submit()', wf_core.translate ('ASSIGN'), wfa_html.image_loc, null, wf_core.translate ('ASSIGN')); htp.p(''); end if; end if; htp.p(''); htp.tablerowclose; htp.tableclose; htp.tableRowClose; htp.tableClose; -- Create hidden fields -- NOTE: Do NOT create any more fields for h_names or h_values here. The -- submit buttons created above must be the last values for these fields -- to work around an MSIE bug that always sends the submit button last. if (status = 'OPEN') then htp.formHidden('h_fdocnames', null); htp.formHidden('h_counter', to_char(respcnt+1), null); htp.formHidden('h_nid', nid); htp.formClose; end if; -- Page footer Wfa_Sec.Footer; htp.htmlClose; exception when others then if (attrs%isopen) then close attrs; -- Close cursor just in case end if; rollback; wf_core.context('Wfa_Html', 'ResponseFrame', nid, nkey); wfa_html.Error; end ResponseFrame; -- -- ForwardFrame -- generate forward frame contents -- IN -- nid - notification id -- nkey - notification access key (for mailed html only) -- procedure ForwardFrame( nid in varchar2, nkey in varchar2) as username varchar2(320); recipient varchar2(320); realname varchar2(360); status varchar2(8); s0 varchar2(2000); lang_codeset varchar2(50); -- Language Codeset from environment -- (e.g. WE8ISO8859P1) l_message varchar2(240) := wfa_html.replace_onMouseOver_quotes(wf_core.translate ('WFPREF_LOV')); l_url varchar2(1000); l_media varchar2(240) := wfa_html.image_loc; l_icon varchar2(30) := 'FNDILOV.gif'; begin -- Authenticate user username := Wfa_Html.Authenticate(to_number(nid), nkey); Wf_Notification.GetInfo(to_number(nid), recipient, s0, s0, s0, s0, status); Wf_Directory.GetRoleInfo(recipient, realname, s0, s0, s0, s0); -- Get language codeset lang_codeset := substr(userenv('LANGUAGE'),instr(userenv('LANGUAGE'),'.')+1, length(userenv('LANGUAGE'))); -- Header and Page Title htp.htmlOpen; htp.headOpen; if (status = 'OPEN') then htp.title(wf_core.translate('WFA_DTITLE')||' '||realname); else htp.title(wf_core.translate('WFA_CDTITLE')||' '||realname); end if; fnd_document_management.get_open_dm_display_window; --1578431: Moved the form submission into a javascript function to perform -- field validation. htp.p('' || wf_core.newline); htp.p(''); htp.headClose; -- Body contents wfa_sec.header(background_only=>TRUE); -- Open form and add hidden fields htp.formOpen(curl=>owa_util.get_owa_service_path||'wfa_html.SubmitForward', cmethod=>'Post', cattributes=>'NAME="WF_HTML"'); htp.formHidden('nkey', nkey); htp.formHidden('h_nid', nid); -- Forwardee field htp.tableOpen(calign=>'CENTER', cattributes=>'summary=""'); htp.tableRowOpen; htp.tableData(cvalue=>'', calign=>'right', cattributes=>'id=""'); htp.formHidden('forwardee', null); -- add LOV here: Note:bottom is name of frame. -- Note: The REPLACE function replaces all the space characters with -- the proper escape sequence. l_url := 'javascript:fnd_open_dm_display_window('||''''|| REPLACE('wf_lov.display_lov?p_lov_name='||'owner'|| '&p_display_name='||'WFA_FIND_USER'|| '&p_validation_callback=wfa_html.wf_user_val'|| '&p_dest_hidden_field=top.opener.parent.bottom.document.WF_HTML.forwardee.value'|| '&p_current_value=top.opener.parent.bottom.document.WF_HTML.display_forwardee.value'|| '&p_display_key='||'Y'|| '&p_dest_display_field=top.opener.parent.bottom.document.WF_HTML.display_forwardee.value', ' ', '%20')||''''||',500,500)'; -- print everything together so ther is no gap. htp.tabledata(htf.formText(cname=>'display_forwardee', csize=>30, cmaxlength=>240, cattributes=>'id="i_assignto"')|| ''|| ''||
                    l_message||'', cattributes=>'id=""'); htp.tableRowClose; -- Delegate/Transfer field htp.tableRowOpen; htp.tableData(cvalue=>'', calign=>'left', ccolspan=>2, cattributes=>'id=""'); htp.tableRowClose; htp.tableRowOpen; htp.tableData(cvalue=>'', calign=>'left', ccolspan=>2, cattributes=>'id=""'); htp.tableRowClose; -- Always treat it as Delegate for now -- htp.formHidden('fmode','DELEGATE'); -- Comments field htp.tableRowOpen; htp.tableData(cvalue=>'', calign=>'right', cattributes=>'id=""'); htp.tableData(cvalue=>htf.formTextarea2(cname=>'comments', nrows=>2, ncolumns=>65, cwrap=>'SOFT', cattributes=>'id="i_comments"'), calign=>'left', cattributes=>'id=""'); htp.tableRowClose; htp.formClose; htp.tableclose; -- Add submit button htp.tableopen(calign=>'CENTER', cattributes=>'summary=""'); htp.tableRowOpen; htp.p(''); --1578431: Changed button to call SubmitForward() javascript function. wfa_html.create_reg_button ('javascript:SubmitForward()', wf_core.translate ('WFMON_OK'), wfa_html.image_loc, 'FNDJLFOK.gif', wf_core.translate ('WFMON_OK')); htp.p(''); htp.p(''); wfa_html.create_reg_button ('Wfa_Html.ResponseFrame?nid='||nid|| '&nkey='||nkey, wf_core.translate ('CANCEL'), wfa_html.image_loc, 'FNDJLFCN.gif', wf_core.translate ('CANCEL')); htp.p(''); htp.tableRowClose; htp.tableClose; wfa_sec.Footer; htp.htmlClose; exception when others then rollback; wf_core.context('Wfa_Html', 'ForwardFrame', nid, nkey); wfa_html.Error; end ForwardFrame; -- -- AttributeInfo -- Generate page with details about a response attribute -- IN -- nid - notification id -- name - attribute name -- procedure AttributeInfo( nid in varchar2, name in varchar2) is dispname varchar2(80); description varchar2(240); attrtype varchar2(8); format varchar2(240); dlookup varchar2(80); begin -- Note: No user authentication is done here to save time, since -- there is nothing secret about attribute descriptions. -- Get attribute info begin select MA.DISPLAY_NAME, MA.DESCRIPTION, MA.TYPE, MA.FORMAT into dispname, description, attrtype, format from WF_NOTIFICATION_ATTRIBUTES NA, WF_MESSAGE_ATTRIBUTES_VL MA, WF_NOTIFICATIONS N where N.NOTIFICATION_ID = to_number(AttributeInfo.nid) and NA.NOTIFICATION_ID = N.NOTIFICATION_ID and MA.MESSAGE_NAME = N.MESSAGE_NAME and MA.MESSAGE_TYPE = N.MESSAGE_TYPE and MA.NAME = NA.NAME and MA.NAME = AttributeInfo.name; exception when no_data_found then wf_core.token('NID', nid); wf_core.token('ATTRIBUTE', name); wf_core.raise('WFNTF_ATTR'); end; -- Header and Page Title htp.htmlOpen; htp.headOpen; htp.title(wf_core.translate('WFA_ATTRINFO')||': '||dispname); htp.headClose; -- Body contents wfa_sec.header(background_only=>TRUE); -- Title htp.center(htf.bold(wf_core.translate('WFA_ATTRINFO')||' '||dispname)); htp.tableOpen(cattributes=>'summary=""'); -- Description htp.tableRowOpen; htp.tableData(cvalue=>wf_core.translate('DESCRIPTION'), calign=>'right', cattributes=>'id=""'); htp.tableData(cvalue=>htf.bold(description), calign=>'left', cattributes=>'bgcolor=white ehaders=""'); htp.tableRowClose; -- Type htp.tableRowOpen; htp.tableData(cvalue=>wf_core.translate('TYPE'), calign=>'right', cattributes=>'id=""'); htp.tableData(cvalue=>htf.bold(wfa_html_util.GetLookupMeaning('WFSTD_ATTRTYPE', attrtype)), calign=>'left', cattributes=>'bgcolor=white id=""'); htp.tableRowClose; -- Format htp.tableRowOpen; if (attrtype = 'VARCHAR2') then htp.tableData(cvalue=>wf_core.translate('MAXLENGTH'), calign=>'right'); htp.tableData(cvalue=>htf.bold(nvl(format, '2000')), calign=>'left', cattributes=>'bgcolor=white'); elsif (attrtype = 'LOOKUP') then htp.tableData(cvalue=>wf_core.translate('LOOKUP'), calign=>'right', cattributes=>'id=""'); -- Get displayed name of lookup begin select WLT.DISPLAY_NAME into dlookup from WF_LOOKUP_TYPES WLT where WLT.LOOKUP_TYPE = AttributeInfo.format; exception when no_data_found then dlookup := format; end; htp.tableData(cvalue=>htf.bold(dlookup), calign=>'left', cattributes=>'bgcolor=white id=""'); elsif format is not null then -- All others just print format only if it exists -- printing "default" is confusing UI. htp.tableData(cvalue=>wf_core.translate('FORMAT'), calign=>'right', cattributes=>'id=""'); htp.tableData(cvalue=>htf.bold(nvl(format, '&'||'lt;'|| wf_core.translate('DEFAULT')||'&'||'gt;')), calign=>'left', cattributes=>'bgcolor=white id=""'); end if; htp.tableRowClose; htp.tableClose; wfa_sec.Footer; htp.htmlClose; exception when others then rollback; wf_core.context('Wfa_Html', 'AttributeInfo', nid, name); wfa_html.Error; end AttributeInfo; -- -- RespFrameSize (RPIVATE) -- Calculate size of response frame using heuristic -- IN -- nid - notification id -- RETURNS -- Size of response frame in pixels -- function RespFrameSize( nid in number) return number is respcnt pls_integer; longcnt pls_integer; urlcnt pls_integer; respsize pls_integer; begin -- Approximate size of response frame using heuristic: -- The rule of thumb being : -- 1. Each non-result response counts as 40 pixels -- + url and multiline fields count twice -- + 1 for result button line -- 2. Frame must be in range 100 - 250 pixels -- 3. If there is a url respond attributet then go for the max size -- Count of multiline response fields select count(1) into urlcnt from WF_MESSAGE_ATTRIBUTES MA, WF_NOTIFICATIONS N where N.NOTIFICATION_ID = nid and MA.MESSAGE_NAME = N.MESSAGE_NAME and MA.MESSAGE_TYPE = N.MESSAGE_TYPE and MA.SUBTYPE = 'RESPOND' and MA.TYPE = 'URL'; if (urlcnt = 1) then respsize := 250; else -- Count of all response fields select count(1) into respcnt from WF_NOTIFICATION_ATTRIBUTES NA, WF_MESSAGE_ATTRIBUTES MA, WF_NOTIFICATIONS N where N.NOTIFICATION_ID = nid and NA.NOTIFICATION_ID = N.NOTIFICATION_ID and MA.MESSAGE_NAME = N.MESSAGE_NAME and MA.MESSAGE_TYPE = N.MESSAGE_TYPE and MA.NAME = NA.NAME and MA.SUBTYPE = 'RESPOND' and MA.TYPE <> 'FORM' and MA.NAME <> 'RESULT'; -- Count of multiline response fields select count(1) into longcnt from WF_NOTIFICATION_ATTRIBUTES NA, WF_MESSAGE_ATTRIBUTES MA, WF_NOTIFICATIONS N where N.NOTIFICATION_ID = nid and NA.NOTIFICATION_ID = N.NOTIFICATION_ID and MA.MESSAGE_NAME = N.MESSAGE_NAME and MA.MESSAGE_TYPE = N.MESSAGE_TYPE and MA.NAME = NA.NAME and MA.SUBTYPE = 'RESPOND' and MA.TYPE = 'VARCHAR2' and decode(MA.TYPE, 'VARCHAR2', nvl(to_number(MA.FORMAT), 2000), 0) > 80; respsize := (respcnt + longcnt + 1) * 40; if (respsize < 100) then respsize := 100; elsif (respsize > 250) then respsize := 250; end if; end if; return(respsize); exception when others then wf_core.context('Wfa_Html', 'RespFrameSize', to_char(nid)); raise; end RespFrameSize; -- -- Detail (PROCEDURE) -- generate detail screen -- IN -- nid - notification id -- NOTE -- Detail is overloaded. -- This version is used by the Web notifications page. -- procedure Detail( nid in varchar2) is recipient varchar2(320); realname varchar2(360); s0 varchar2(2000); status varchar2(8); respsize pls_integer; username varchar2(320); url_str varchar2(4000); showforms varchar2(1); begin -- Get status Wf_Notification.GetInfo(to_number(nid), recipient, s0, s0, s0, s0, status); username := Wfa_Html.Authenticate(to_number(nid), null); Wf_Directory.GetRoleInfo(username, realname, s0, s0, s0, s0); htp.htmlOpen; htp.headOpen; if (status = 'OPEN') then htp.title(wf_core.translate('WFA_DTITLE') || ' ' || realname); else htp.title(wf_core.translate('WFA_CDTITLE') || ' ' || realname); end if; wfa_html.create_help_function('wf/links/det.htm?DETNOT'); -- Add the java script to the header to open the dm window for -- any DM function that is executed. fnd_document_management.get_open_dm_display_window; htp.headClose; -- Calculate size of response frame respsize := RespFrameSize(to_number(nid)); -- Open frameset, and set focus to response window. -- NOTE: MSIE does not support focus method. if (instr(owa_util.get_cgi_env('HTTP_USER_AGENT'), 'MSIE') <> 0) then htp.p(''); else htp.p(''); end if; -- Descide to show Forms or not if (Wf_Core.translate('WF_INSTALL') = 'EMBEDDED') then showforms := 'T'; else showforms := ''; end if; if (showforms is not null) then htp.p(''); else htp.p(''); end if; url_str := owa_util.get_owa_service_path|| 'wfa_html.ResponseFrame?nid='||nid; if (showforms is not null) then url_str := url_str||'&'||'showforms=T'; end if; -- Note frame name BOTTOM is hardcoded into wfa_html.detail htp.p(''); htp.p(''); htp.htmlClose; exception when others then rollback; wf_core.context('Wfa_Html','Detail', nid); wfa_html.Error; end Detail; -- -- Detail (FUNCTION) -- return standalone detail screen text -- IN -- nid - notification id -- nkey - notification key -- agent - web agent URL root -- NOTE -- Detail is overloaded. -- This produces the version used by the mailer. function Detail( nid in number, nkey in varchar2, agent in varchar2) return varchar2 as username varchar2(320); status varchar2(8); realname varchar2(360); s0 varchar2(240); result varchar2(32000); respsize pls_integer; key varchar2(255); n_sig_policy varchar2(100); begin Wf_Mail.GetSignaturePolicy(nid, n_sig_policy); if (wf_mail.send_accesskey and n_sig_policy not in ('PSIG_ONLY')) then key := nkey; -- Authenticate the user has access username := Wfa_Html.Authenticate(nid, nkey); -- Get notification recipient and status Wf_Notification.GetInfo(nid, username, s0, s0, s0, s0, status); Wf_Directory.GetRoleInfo(username, realname, s0, s0, s0, s0); -- Set title result := htf.htmlOpen ||g_newLine; result := result || htf.headOpen||g_newLine; if (status = 'OPEN') then result := result || htf.title(wf_core.translate('WFA_DTITLE')||' '||realname)|| g_newLine; else result := result || htf.title(wf_core.translate('WFA_CDTITLE')||' '||realname)|| g_newLine; end if; --tr: dont execute the help function --it calls htp procs which causes session to hang -- wfa_html.create_help_function('wf/links/det.htm?DETNOT'); result := result || htf.headClose||g_newLine; -- Calculate size of response frame respsize := RespFrameSize(nid); -- Open frameset. -- NOTE: Do NOT set the focus here, because it is not supported on -- all platforms, and it is unknown at this point what browser will -- be used to display the html returned to the mailer. result := result||''|| g_newLine; result := result || ''||g_newLine; result := result || ''||g_newLine; result := result || ''||g_newLine; result := result || htf.htmlClose; else -- Send_accesskey is set to N so we will generate a DirectLogin call. -- We do not need to authenticate the user, since the user will have -- to authenticate to view the notification. After authentication, -- DirectLogin will redirect to the Detail (Web-interface) procedure so -- we will then confirm that the user logged in can also view the -- notification. key := NULL; result := htf.htmlOpen ||g_newLine; result := result || htf.headOpen||g_newLine; result := result || htf.title(wf_core.translate('WFA_LOGIN_REQUEST'))|| g_newLine; result := result || htf.headClose||g_newLine; result := result||''||g_newLine; result := result || ''||g_newLine; result := result || ''||g_newLine; result := result || htf.htmlClose; end if; return(result); exception when others then wf_core.context('Wfa_Html', 'Detail', to_char(nid), nkey, agent); raise; end Detail; -- -- Detail2 (FUNCTION) -- return standalone detail screen text -- IN -- nid - notification id -- nkey - notification key -- agent - web agent URL root -- NOTE -- Detail is overloaded. -- This produces the version used by the mailer. function Detail2( nid in number, nkey in varchar2, agent in varchar2) return varchar2 as username varchar2(320); status varchar2(8); realname varchar2(360); s0 varchar2(240); result varchar2(32000); n_sig_policy varchar2(100); url varchar2(4000); l_function_id number; params varchar2(240); validateAccess varchar2(1); begin -- Authenticate the user has access username := Wfa_Html.Authenticate(nid, nkey); -- Get notification recipient and status Wf_Notification.GetInfo(nid, username, s0, s0, s0, s0, status); Wf_Directory.GetRoleInfo(username, realname, s0, s0, s0, s0); -- Set title result := htf.htmlOpen ||g_newLine; result := result || htf.headOpen||g_newLine; if (status = 'OPEN') then result := result || htf.title(wf_core.translate('WFA_DTITLE')||' '||realname)|| g_newLine; else result := result || htf.title(wf_core.translate('WFA_CDTITLE')||' '||realname)|| g_newLine; end if; result := result || htf.headClose||g_newLine; -- Open frameset. -- NOTE: Do NOT set the focus here, because it is not supported on -- all platforms, and it is unknown at this point what browser will -- be used to display the html returned to the mailer. if g_wfInstall='EMBEDDED' then result := result||''||g_newLine; url := wf_mail.Get_Ntf_Function_URL(nid => nid, n_key => nkey, n_sig_policy => n_sig_policy); result := result || ''||g_newLine; result := result || ''||g_newLine; result := result || htf.htmlClose; else -- While the call is within standalone, continue to ---operate as before. result := wfa_html.detail(nid, nkey, agent); end if; return(result); exception when others then wf_core.context('Wfa_Html', 'Detail', to_char(nid), nkey, agent); raise; end Detail2; -- DetailLink -- display standalone detail screen text -- IN -- nid - notification id -- nkey - notification key -- agent - web agent URL root -- NOTE -- Detaillink called function Detail above. -- This produces the version used by the mailer. procedure DetailLink( nid in number, nkey in varchar2, agent in varchar2) is m_html varchar2(32000); begin m_html := Wfa_Html.Detail2(nid, nkey, agent); htp.p(m_html); exception when others then wf_core.context('Wfa_Html', 'DetailLink', to_char(nid), nkey, agent); raise; end DetailLink; -- SubmitForward -- Submit notification forward -- IN -- h_nid - notification id -- forwardee - new recipient field -- display_forwardee - display name for the new recipient -- comments - forwarding comments field -- fmode - reassign mode can be: -- transfer - transferring responsibility -- delegate - delegate responsibility -- submit - submit forward button -- cancel - cancel forward button -- nkey - access key for mailed html procedure SubmitForward( h_nid in varchar2, forwardee in varchar2, display_forwardee in varchar2, comments in varchar2, fmode in varchar2, submit in varchar2, cancel in varchar2, nkey in varchar2) is nid pls_integer; username varchar2(320); l_forwardee varchar2(320); pseudo_login boolean := FALSE; begin -- If CANCEL button, swap frame to ResponseFrame and exit. if (cancel is not null) then Wfa_Html.ResponseFrame(h_nid, nkey); return; end if; if (nkey is not null) then pseudo_login := TRUE; end if; -- Fully resolve forwardee name l_forwardee := forwardee; wfa_html.validate_display_name (display_forwardee, l_forwardee); -- REASSIGN button. -- Authenticate user nid := to_number(h_nid); username := Wfa_Html.Authenticate(nid, nkey); -- Make sure the comments field is <= 240. if ( lengthb(comments) > 240 ) then WF_CORE.Raise('WFA_MAX_COMMENTS'); end if; -- Submit the forward if (fmode = 'DELEGATE') then if (comments is not null) then -- ### implement this in next release -- wf_notification.Forward(nid, upper(l_forwardee), comments, username); wf_notification.Forward(nid, upper(l_forwardee), comments); else -- ### implement this in next release -- wf_notification.Forward(nid, upper(l_forwardee), '', username); wf_notification.Forward(nid, upper(l_forwardee)); end if; elsif (fmode = 'TRANSFER') then if (comments is not null) then -- ### implement this in next release -- wf_notification.Transfer(nid,upper(l_forwardee), comments, username); wf_notification.Transfer(nid,upper(l_forwardee), comments); else -- ### implement this in next release -- wf_notification.Transfer(nid,upper(l_forwardee), '', username); wf_notification.Transfer(nid,upper(l_forwardee)); end if; end if; if (pseudo_login) then htp.htmlOpen; htp.headOpen; htp.center(htf.bold(WF_CORE.Translate('WFA_ASSIGNED') || ': ' || WF_DIRECTORY.GetRoleDisplayName(upper(l_forwardee)) || '.')); htp.headClose; htp.htmlClose; else -- Putting WorkList in the browser window Wfa_Html.GotoURL('Wfa_Html.WorkList', '_top'); end if; exception when others then rollback; wf_core.context('Wfa_Html','SubmitForward', h_nid, nkey, forwardee, comments); wfa_html.Error; end SubmitForward; -- SubmitResponse -- Submit notification response -- IN -- h_nid - notification id -- h_fnames - array of field names -- h_fvalues - array of field values -- h_fdocnames - array of documentnames - a throwaway value from form -- h_counter - number of fields passed in fnames and fvalues -- submit - submit response button -- forward - forward button -- nkey - access key for mailed html procedure SubmitResponse( h_nid in varchar2, h_fnames in Name_Array, h_fvalues in Value_Array, h_fdocnames in Value_Array, h_counter in varchar2, submit in varchar2, forward in varchar2, nkey in varchar2) as nid pls_integer; username varchar2(320); x pls_integer; pseudo_login boolean := FALSE; begin -- If FORWARD button, swap frame to ForwardFrame and exit. if (forward is not null) then Wfa_Html.ForwardFrame(h_nid, nkey); return; end if; if (nkey is not null) then pseudo_login := TRUE; end if; -- One of RESPOND buttons pushed - submit response. -- Authenticate user nid := to_number(h_nid); username := Wfa_Html.Authenticate(nid, nkey); -- Set attributes in the reponse array. -- Start at 2 to step over the Dummy_Name/Dummy_Value pair added at -- the start of the array. for x in 2 .. to_number(h_counter) loop wfa_html_util.SetAttribute(nid, h_fnames(x), h_fvalues(x), h_fdocnames(x)); end loop; -- Submit response -- If there is a problem, go back to the ResponseFrame -- otherwise, go back to the worklist begin -- Do not need to preserve context wf_engine.preserved_context := FALSE; wf_notification.Respond(nid, null, username); exception when others then -- ### We do not want this now. Since there is real error message -- ### we want users to see, we raise an exception instead. -- Reload response window to reflect changes -- Wfa_Html.ResponseFrame(h_nid, nkey); -- When an exception ocurr, raise it and show the error stack. raise; end; if (pseudo_login) then Wfa_Html.ResponseFrame(h_nid, nkey); else -- Putting WorkList in the browser window Wfa_Html.GotoURL('Wfa_Html.WorkList', '_top'); end if; exception when others then rollback; wf_core.context('Wfa_Html','SubmitResponse', h_nid, nkey, submit, forward); wfa_html.Error; end SubmitResponse; -- GotoURL -- GotoURL let you open an url in a specify place. This is very useful -- when you need to go from a child frame to the full browser window, -- for instnace. -- So far, this is the only way to break away from a child frame. -- IN -- url - Fully qualified universal resouce location -- location - Where you want to open it. Samples of values are -- _blank - unnamed window -- _self - the current frame -- _parent - the parent frame of the current one -- _top - the full Web browser window -- "myWin" - name of the new window -- procedure GotoURL( url in varchar2, location in varchar2, attributes in varchar2 ) is begin htp.htmlOpen; htp.headOpen; htp.p(''); htp.p(''); htp.headClose; if (attributes is null) then htp.p (''); else htp.p (''); end if; htp.bodyClose; htp.htmlClose; end; -- SubmitSelectedResponse -- Submit selected notification response -- IN -- nids - notification ids -- close - submit response button -- forward - forward button -- showto - display the TO column -- nkey - access key for mailed html procedure SubmitSelectedResponse( nids in Name_Array, close in varchar2, forward in varchar2, showto in varchar2, nkey in varchar2) as username varchar2(320); -- Username to query n_priority varchar2(80); -- priority icon n_response varchar2(80); -- required response icon l_message varchar2(240) := wf_core.translate ('WFPREF_LOV'); lang_codeset varchar2(50); -- Language Codeset from environment -- (e.g. WE8ISO8859P1) nid pls_integer; x pls_integer; l_url varchar2(1000); l_media varchar2(240) := wfa_html.image_loc; l_icon varchar2(30) := 'FNDILOV.gif'; cursor s_cursor(mnid in number) is select NID, PRIORITY, LANGUAGE, MESSAGE_TYPE, RECIPIENT_ROLE, SUBJECT, BEGIN_DATE, DUE_DATE, END_DATE, DISPLAY_STATUS, STATUS, FROM_USER, TO_USER from WF_WORKLIST_V where NID = mnid; cursor attrs(mnid in number) is select MA.NAME from WF_NOTIFICATION_ATTRIBUTES NA, WF_MESSAGE_ATTRIBUTES_VL MA, WF_NOTIFICATIONS N where N.NOTIFICATION_ID = mnid and NA.NOTIFICATION_ID = N.NOTIFICATION_ID and MA.MESSAGE_NAME = N.MESSAGE_NAME and MA.MESSAGE_TYPE = N.MESSAGE_TYPE and MA.NAME = NA.NAME and MA.SUBTYPE = 'RESPOND' and MA.TYPE <> 'FORM' and MA.NAME = 'RESULT'; notrec s_cursor%rowtype; result attrs%rowtype; begin -- If no nid was passed in, it failed before reaching to this -- procedure. -- There is always a dummy nid passed in. We will handle it here. -- Make sure subsequent index start at 2 not 1. if (to_number(nids.count) = 1) then wf_core.raise('WFNTF_NO_SELECT'); end if; -- Get language codeset lang_codeset := substr(userenv('LANGUAGE'),instr(userenv('LANGUAGE'),'.')+1, length(userenv('LANGUAGE'))); if (forward is not null) then -- Delegating ... -- Submit Everything to the form that get forwardee and comment htp.htmlOpen; htp.headOpen; htp.title(wf_core.translate('WFA_FORWARDTITLE')); wfa_html.create_help_function('wf/links/fwd.htm?FWD_WEB'); fnd_document_management.get_open_dm_display_window; htp.headClose; wfa_sec.Header(FALSE, owa_util.get_owa_service_path ||'wfa_html.Find', wf_core.translate('WFA_FORWARDTITLE'), TRUE); htp.formOpen(curl=>owa_util.get_owa_service_path||'wfa_html.ForwardNids', cmethod=>'POST', cattributes=>'TARGET="_top" NAME="WF_HTML"'); -- Dummy Hidden H_NIDS Field to handle situation when nothing is selected htp.formHidden('H_NIDS', -1); -- Forwardee field htp.tableOpen (calign=>'CENTER', cattributes=>'summary=""'); htp.tableRowOpen; htp.tableData(cvalue=>'', calign=>'right', cattributes=>'id=""'); htp.formHidden('forwardee', null); -- add LOV here: Note:bottom is name of frame. -- Note: The REPLACE function replaces all the space characters with -- the proper escape sequence. l_url := 'javascript:fnd_open_dm_display_window('||''''|| REPLACE('wf_lov.display_lov?p_lov_name='||'owner'|| '&p_display_name='||'WFA_FIND_USER'|| '&p_validation_callback=wfa_html.wf_user_val'|| '&p_dest_hidden_field=top.opener.parent.document.WF_HTML.forwardee.value'|| '&p_current_value=top.opener.parent.document.WF_HTML.display_forwardee.value'|| '&p_display_key='||'Y'|| '&p_dest_display_field=top.opener.parent.document.WF_HTML.display_forwardee.value', ' ', '%20')||''''||',500,500)'; -- print everything together so ther is no gap. htp.tabledata(htf.formText(cname=>'display_forwardee', csize=>30, cmaxlength=>360, cattributes=>'id="i_assignto"')|| ''|| ''||
                    l_message||'', cattributes=>'id=""'); htp.tableRowClose; -- Delegate/Transfer field htp.tableRowOpen; htp.tableData(cvalue=>'', calign=>'left', ccolspan=>2, cattributes=>'id=""'); htp.tableRowClose; htp.tableRowOpen; htp.tableData(cvalue=>'', calign=>'left', ccolspan=>2, cattributes=>'id=""'); htp.tableRowClose; -- Always treat it as Delegate for now -- htp.formHidden('fmode', 'DELEGATE'); -- Comments field htp.tableRowOpen; htp.tableData(cvalue=>'', calign=>'right', cattributes=>'id=""'); htp.tableData(cvalue=>htf.formTextarea2(cname=>'comments', nrows=>2, ncolumns=>65, cwrap=>'SOFT'), calign=>'left', cattributes=>'id="i_comments"'); htp.tableRowClose; htp.tableClose; -- Submit and cancel buttons htp.tableopen(calign=>'CENTER', cattributes=>'summary=""'); htp.tableRowOpen; htp.p(''); wfa_html.create_reg_button ('javascript:document.WF_HTML.submit()', wf_core.translate ('WFMON_OK'), wfa_html.image_loc, 'FNDJLFOK.gif', wf_core.translate ('WFMON_OK')); htp.p(''); htp.p(''); wfa_html.create_reg_button ('javascript:window.history.back()', wf_core.translate ('CANCEL'), wfa_html.image_loc, 'FNDJLFCN.gif', wf_core.translate ('CANCEL')); htp.p(''); htp.tableRowClose; htp.tableClose; htp.br; -- There are some notifications for the user. Construct the page. htp.tableOpen('border=1 cellpadding=3 bgcolor=white width=100% summary=""'); -- Column headers htp.tableRowOpen(cattributes=>'bgcolor=#006699'); htp.tableHeader(cvalue=>'', calign=>'Center', cattributes=>'id="' || WF_CORE.Translate('SELECT') || '"'); htp.tableHeader(cvalue=>''|| wf_core.translate('PRIORITY')||'', calign=>'Center', cattributes=>'id="' || WF_CORE.Translate('PRIORITY') || '"'); htp.tableHeader(''||wf_core.translate('TYPE')|| '', 'Center', cattributes=>'id="' || WF_CORE.Translate('TYPE') || '"'); htp.tableHeader(''||wf_core.translate('FROM')|| '', 'Center', cattributes=>'id="' || WF_CORE.Translate('FROM') || '"'); if (showto = 'T') then htp.tableHeader(''||wf_core.translate('TO')|| '', 'Center', cattributes=>'id="' || WF_CORE.Translate('TO') || '"'); end if; htp.tableHeader(''||wf_core.translate('SUBJECT') ||'', 'Center', cattributes=>'id="' || WF_CORE.Translate('SUBJECT') || '"'); htp.tableHeader(''|| wf_core.translate('BEGIN_DATE')||'', 'Center', cattributes=>'id="' || WF_CORE.Translate('BEGIN_DATE') || '"'); htp.tableHeader(''|| wf_core.translate('DUE_DATE')||'', 'Center', cattributes=>'id="' || WF_CORE.Translate('DUE_DATE') || '"'); htp.tableRowClose; -- Print summary for x in 2 .. to_number(nids.count) loop open s_cursor(nids(x)); fetch s_cursor into notrec; if (s_cursor%notfound) then Wf_Core.Token('NID', nids(x)); Wf_Core.Raise('WFNTF_NID'); exit; end if; close s_cursor; -- Figure out the priority first n_priority := GetPriorityIcon(notrec.priority); -- Figure out whether response is required n_response := null; if (notrec.status = 'OPEN') then open attrs(notrec.nid); fetch attrs into result; if (attrs%found) then n_response := wfa_html.image_loc||'reqresp.gif'; end if; close attrs; end if; -- Displaying a row htp.tableRowOpen(null, 'TOP'); -- We can check nids in this way because nids will be in the same -- order of the query. -- htp.tableData(htf.formCheckbox(cname=>'H_NIDS', cvalue=>notrec.nid, cchecked=>1, cattributes=>'id="i_select"'), 'center', cattributes=>'headers="' || WF_CORE.Translate('SELECT') || '"'); htp.p(''); htp.tableOpen('border=0 width="100%" summary=""'); htp.tableRowOpen(null,'TOP'); if (n_priority is null) then -- ### width below is ignored in html code, took it out. -- htp.tableData('&'||'nbsp;', 'left', 'width="50%"'); htp.tableData('&'||'nbsp;', 'left', cattributes=>'headers="' || WF_CORE.Translate('PRIORITY') || '"'); else htp.tableData(htf.img(curl=>n_priority, calt=>WFA_HTML.g_priority), 'center', cattributes=>'headers="' || WF_CORE.Translate('PRIORITY') || '"'); end if; htp.tableRowClose; htp.tableClose; htp.p(''); htp.tableData(notrec.message_type, 'left', cattributes=>'headers="' || WF_CORE.Translate('TYPE') || '"'); htp.tableData(nvl(notrec.from_user, ' '), 'left', cattributes=>'headers="' || WF_CORE.Translate('FROM') || '"'); if (showto = 'T') then htp.tableData(notrec.to_user, 'left', cattributes=>'id="' || WF_CORE.Translate('TO') || '"'); end if; -- If response is required, append response required icon to subject if (n_response is null) then htp.tableData(notrec.subject, calign=>'left', cattributes=>'headers="' || WF_CORE.Translate('SUBJECT') || '"'); else htp.tableData( cvalue=>notrec.subject||'&'|| 'nbsp;'||htf.img(curl=>n_response, calt=>WF_CORE.Translate('WFSRV_RECIPIENT_MUST_RESPOND')), calign=>'left', cattributes=>'headers="' || WF_CORE.Translate('SUBJECT') || '"'); end if; htp.tableData(cvalue=>to_char(notrec.begin_date ), calign=>'left', cnowrap=>1, cattributes=>'headers="' || WF_CORE.Translate('BEGIN_DATE') || '"'); htp.tableData(cvalue=>nvl(to_char(notrec.due_date), '
'), calign=>'left', cnowrap=>1, cattributes=>'headers="' || WF_CORE.Translate('DUE_DATE') || '"'); htp.tableRowClose; end loop; htp.tableClose; htp.formHidden('nkey',nkey); htp.formClose; htp.htmlClose; goto worklist; end if; -- For each nid, do the appropriate operation for x in 2..nids.count loop nid := to_number(nids(x)); -- Authenticate user username := Wfa_Html.Authenticate(nid, nkey); if (close is not null) then -- Closing and other activities ... begin wf_notification.Close(nid,username); exception when others then raise; end; end if; end loop; -- Go back to WorkList Screen -- ### Using GotoURL here will be a bit costly, but has a nice side effect -- ### that the "Location" indicated in the browser will match that of -- ### what you see. -- ### Wfa_html.GotoURL('Wfa_Html.WorkList'); Wfa_html.WorkList; -- -- Go back to the previous function that will go back to WorkList screen -- <> return; exception when others then rollback; if (s_cursor%isopen) then close s_cursor; end if; if (attrs%isopen) then close attrs; end if; wf_core.context('Wfa_Html','SubmitSelectedResponse', user); wfa_html.Error; end SubmitSelectedResponse; -- ForwardNids -- Forward for each notification ids -- Forward can be Delegating or Transferring -- Delegating is for notification only. -- Transferring is reassign the whole responsibility to other -- IN -- h_nids - hidden notification ids -- forwardee - forwardee role specified -- comments - comments included -- fmode - reassign mode can be: -- transfer - transferring responsibility -- delegate - delegate responsibility -- cancel - cancel button procedure ForwardNids( h_nids in Name_Array, forwardee in varchar2, display_forwardee in varchar2, comments in varchar2, fmode in varchar2, submit in varchar2, cancel in varchar2, nkey in varchar2) as username varchar2(320); x pls_integer; nid pls_integer; l_forwardee varchar2(320); begin -- There is always a dummy nid passed in. We will handle it here. -- Make sure subsequent index start at 2 not 1. if (to_number(h_nids.count) = 1) then wf_core.raise('WFNTF_NO_SELECT'); end if; -- Fully resolve forwardee name l_forwardee := forwardee; wfa_html.validate_display_name (display_forwardee, l_forwardee); -- Otherwise, for each notification, delegate or transfer for x in 2..h_nids.count loop -- Authenticate user nid := to_number(h_nids(x)); username := Wfa_Html.Authenticate(nid, nkey); -- Delegating to forwardee with comments if (fmode = 'DELEGATE') then if (comments is not null) then -- ### implement this in next release -- Wf_Notification.Forward(nid, upper(l_forwardee), comments, username); Wf_Notification.Forward(nid, upper(l_forwardee), comments); else -- ### implement this in next release -- Wf_Notification.Forward(nid, upper(l_forwardee), '', username); Wf_Notification.Forward(nid, upper(l_forwardee)); end if; elsif (fmode = 'TRANSFER') then -- Transferring to fowardee with comments if (comments is not null) then -- ### implement this in next release -- Wf_Notification.Transfer(nid, upper(l_forwardee), comments, username); Wf_Notification.Transfer(nid, upper(l_forwardee), comments); else -- ### implement this in next release -- Wf_Notification.Transfer(nid, upper(l_forwardee), '', username); Wf_Notification.Transfer(nid, upper(l_forwardee)); end if; end if; end loop; -- Back to the worklist <> Wfa_Html.WorkList; return; exception when others then rollback; wfa_html.Error; return; end ForwardNids; /*=========================================================================== PROCEDURE NAME: create_help_function DESCRIPTION: Create the java script function to support the Help Icon from the header Note: The help file parameter must include the subdirectory under /OA_DOC/lang/ and the actual file name which will either be wf or wfnew. ie p_help_file = 'wf/notif16.htm' p_help_file = 'wfnew/wfnew48.htm' ============================================================================*/ procedure create_help_function ( p_help_file IN VARCHAR2 ) IS install_type VARCHAR2(80); l_help_target VARCHAR2(240) := NULL; l_lang VARCHAR2(2000); help_prefix VARCHAR2(2000); BEGIN BEGIN /* ** Get the language environment variable ** for this user. */ SELECT USERENV('LANG') INTO l_lang FROM DUAL; EXCEPTION WHEN OTHERS THEN l_lang := 'US'; END; /* ** Check the installation type. If it is workflow standalone ** then use the file prefix method of getting to the help ** content. Otherwise use the fnd function method to get and ** display the help content. */ install_type := wf_core.translate('WF_INSTALL'); if (install_type = 'STANDALONE') THEN help_prefix := '/OA_DOC/'; htp.p(''); htp.p(''); htp.p(''); else /* ** If you're going against apps then strip out everything ** except the target name */ IF (INSTR(p_help_file, '?') > 0) THEN l_help_target := substrb(p_help_file, INSTR(p_help_file, '?') + 1); ELSE l_help_target := p_help_file; END IF; wfa_sec.create_help_syntax (l_help_target, l_lang); end if; exception when others then Wf_Core.Context('wfa_html', 'create_help_function', p_help_file); wfa_html.Error; END create_help_function; /*=========================================================================== FUNCTION NAME: conv_special_url_chars DESCRIPTION: Convert all of the ASCII special characters that are disallowed as a part of a URL. The encoding requires that we convert the special characters to HEX for any characters in a URL string that is built manually outside a form get/post. This API now also converts multibyte characters into their HEX equivalent. ============================================================================*/ FUNCTION conv_special_url_chars (p_url_token IN VARCHAR2) RETURN VARCHAR2 IS c_unreserved constant varchar2(72) := '-_.!*''()~ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; c_reserved constant varchar2(72) := '%">^{}<[]`|/#?&=$:;+'; l_tmp varchar2(32767) := ''; l_onechar varchar2(4); l_byte_len integer; i integer; l_str varchar2(48); BEGIN if p_url_token is NULL then return NULL; end if; for i in 1 .. length(p_url_token) loop l_onechar := substr(p_url_token,i,1); --Extracting out each character to be replaced. if instr(c_unreserved, l_onechar) > 0 then --Check if it is part of the ASCII unreserved --excluded from encoding just append to the URL --string l_tmp := l_tmp || l_onechar; elsif l_onechar = ' ' then --Space encoded as '%20' l_tmp := l_tmp || '%20'; elsif instr(c_reserved,l_onechar) >0 then --If it is any of the reserved characters in ascii --replace with equivalent HEX l_onechar := REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE(l_onechar, '%','%25'), ' ','%20'), '"','%22'), '>','%3E'), '^','%5E'), '{','%7B'), '}','%7D'), '<','%3C'), '[','%5B'), ']','%5D'), '`','%60'), '|','%7C'), '/','%2F'), '#','%23'), '?','%3F'), '&','%26'), '=','%3D'), '$','%24'), ':','%3A'), ';','%3B'), '+','%2B'), '''','%27'); l_tmp := l_tmp || l_onechar; else --For multibyte -- 1. Obtain length for each character -- 2. ascii(l_char)decimal representation in the database -- character set -- 3. Change it to the format model : -- to_char(ascii(l_onechar),'FM0X') -- 4. Add to the already encoded string. -- characters l_byte_len := lengthb(l_onechar); if l_byte_len = 1 then l_tmp := l_tmp || '%' || substr(to_char(ascii(l_onechar),'FM0X'),1,2); elsif l_byte_len = 2 then l_str := to_char(ascii(l_onechar),'FM0XXX'); l_tmp := l_tmp || '%' || substr(l_str,1,2) || '%' || substr(l_str,3,2); elsif l_byte_len = 3 then l_str := to_char(ascii(l_onechar),'FM0XXXXX'); l_tmp := l_tmp || '%' || substr(l_str,1,2) || '%' || substr(l_str,3,2) || '%' || substr(l_str,5,2); elsif l_byte_len = 4 then l_str := to_char(ascii(l_onechar),'FM0XXXXXXX'); l_tmp := l_tmp || '%' || substr(l_str,1,2) || '%' || substr(l_str,3,2) || '%' || substr(l_str,5,2) || '%' || substr(l_str,7,2); else -- maximum precision wf_core.raise('WFENG_PRECESSION_EXCEED'); end if; end if; end loop; return l_tmp; exception when others then Wf_Core.Context('wfa_html', 'conv_special_url_chars', p_url_token); wfa_html.Error; END conv_special_url_chars; -- -- User_LOV -- Create the data for the User List of Values -- NOTE: This is not used by APPS. Otherwise, we will have performance -- problem with this query against wf_roles. -- procedure User_LOV (p_titles_only IN VARCHAR2, p_find_criteria IN VARCHAR2) IS l_username VARCHAR2(320); l_display_name VARCHAR2(360); -- enlarged from 80 to match db definition l_name VARCHAR2(320); -- enlarged from 30 to match db definition l_row_count NUMBER := 0; CURSOR c_user_lov (c_find_criteria IN VARCHAR2) IS SELECT name, display_name FROM wf_roles WHERE upper(name) like upper(c_find_criteria) AND upper(name) not like '~WF_ADHOC-%' AND status <> 'INACTIVE' ORDER BY name; BEGIN -- Authenticate user wfa_sec.GetSession(l_username); IF (p_titles_only = 'N') THEN SELECT COUNT(*) INTO l_row_count FROM wf_roles WHERE upper(name) like upper(p_find_criteria)||'%' AND upper(name) not like '~WF_ADHOC-%' AND status <> 'INACTIVE'; END IF; htp.p(wf_core.translate('WFA_FIND_USER')); htp.p('2'); htp.p(TO_CHAR(l_row_count)); htp.p(wf_core.translate('NAME')); htp.p('40'); htp.p(wf_core.translate('DISPLAY_NAME')); htp.p('60'); IF (p_titles_only = 'N') THEN OPEN c_user_lov (p_find_criteria||'%'); /* ** Loop through all the language rows for the given find_criteria ** and write them out to the web page */ LOOP FETCH c_user_lov INTO l_name, l_display_name; EXIT WHEN c_user_lov%NOTFOUND; htp.p (l_name); htp.p (l_display_name); END LOOP; END IF; exception when others then rollback; if (c_user_lov%isopen) then close c_user_lov; end if; wf_core.context('Wfa_Html', 'user_lov',p_titles_only, p_find_criteria); wfa_html.Error; end User_Lov; procedure logout is username varchar2(320); begin wfa_sec.GetSession(username); owa_util.mime_header('text/html', FALSE); owa_cookie.send('WDB_GATEWAY_LOGOUT','YES', '', '/'); owa_util.http_header_close; htp.htmlOpen; htp.headOpen; htp.title(wf_core.translate('WFA_HOMETITLE')); wfa_html.create_help_function('wf/links/web.htm?WEBHOME'); htp.headClose; -- Page header wfa_sec.Header(FALSE, '', wf_core.translate('WF_WORKFLOW_TITLE')|| ' - '|| wf_core.translate('WF_VERSION'), FALSE); htp.center(wf_core.translate('LOGOUT_MESSAGE') ||' '||htf.anchor(curl=>wfa_html.base_url||'/wfa_html.home', ctext=>wf_core.translate('CLICK_HOME'))); wfa_sec.Footer; htp.htmlClose; exception when others then wf_core.context('Wfa_Html','logout'); wfa_html.Error; end logout; procedure Home(message in varchar2) is username varchar2(320); -- Username to query realname varchar2(360); -- Display name of username admin_role varchar2(320); -- Role for admin mode admin_mode varchar2(1); -- Does user have admin privledges s0 varchar2(2000); begin BEGIN -- Check session and current user wfa_sec.GetSession(username); username := upper(username); -- Validate the user if (username is null) then -- No username entered wfa_html.Login('WFA_ENTER_ID'); return; end if; EXCEPTION WHEN NO_DATA_FOUND THEN -- No username entered wfa_html.Login('WFA_ENTER_ID'); return; WHEN OTHERS THEN raise; END; wf_directory.GetRoleInfo(username, realname, s0, s0, s0, s0); admin_mode := 'N'; admin_role := wf_core.translate('WF_ADMIN_ROLE'); if (admin_role = '*' or Wf_Directory.IsPerformer(username, admin_role)) then admin_mode := 'Y'; end if; htp.htmlOpen; htp.headOpen; htp.title(wf_core.translate('WFA_HOMETITLE')||' - '||realname); htp.headClose; wfa_html.homemenu; htp.htmlClose; exception when others then rollback; wf_core.context('Wfa_Html','home'); wfa_html.Error; end home; procedure Header is username varchar2(320); -- Username to query begin -- Check session and current user wfa_sec.GetSession(username); -- Set page title htp.htmlOpen; htp.headOpen; htp.title(wf_core.translate('WFA_HOMETITLE')); wfa_html.create_help_function('wf/links/web.htm?WEBHOME'); htp.headClose; -- Page header wfa_sec.Header(FALSE, '', wf_core.translate('WF_WORKFLOW_TITLE')|| ' - '|| wf_core.translate('WF_VERSION'), TRUE); wfa_sec.Footer; htp.htmlClose; end; procedure home_float is username varchar2(320); -- Username to query realname varchar2(360); -- Display name of username admin_role varchar2(320); -- Role for admin mode admin_mode varchar2(1); -- Does user have admin privledges s0 varchar2(2000); close_anchor varchar2(40); begin -- Check session and current user wfa_sec.GetSession(username); username := upper(username); wf_directory.GetRoleInfo(username, realname, s0, s0, s0, s0); admin_mode := 'N'; admin_role := wf_core.translate('WF_ADMIN_ROLE'); if (admin_role = '*' or Wf_Directory.IsPerformer(username, admin_role)) then admin_mode := 'Y'; end if; -- Set page title htp.htmlOpen; htp.headOpen; htp.p(''); htp.p(''); htp.headClose; htp.p(''); htp.p(''); htp.p(''); wfa_sec.Footer; htp.htmlClose; if (admin_mode = 'Y') then wfa_html.WorkList(user=>username,resetcookie=>1); else wfa_html.WorkList(resetcookie=>1); end if; end home_float; -- Homemenu -- Prints the menu for the home page. -- May also be called direct to print a regular page. procedure Homemenu(message in varchar2, origin in varchar2) is username varchar2(320); -- Username to query realname varchar2(360); -- Display name of username admin_role varchar2(320); -- Role for admin mode admin_mode varchar2(1); -- Does user have admin privledges s0 varchar2(2000); anchor_tag varchar2(60); wrklstbuf varchar2(2000); -- buffer to store worklist string begin -- Check session and current user wfa_sec.GetSession(username); username := upper(username); wf_directory.GetRoleInfo(username, realname, s0, s0, s0, s0); admin_mode := 'N'; admin_role := wf_core.translate('WF_ADMIN_ROLE'); if (admin_role = '*' or Wf_Directory.IsPerformer(username, admin_role)) then admin_mode := 'Y'; end if; -- Set page title htp.htmlOpen; htp.headOpen; htp.title(wf_core.translate('WFA_HOMETITLE')); wfa_html.create_help_function('wf/links/web.htm?WEBHOME'); htp.headClose; if origin = 'FLOATING' then anchor_tag := 'TRUE); else anchor_tag := ''); -- User, Admin Mode htp.p(realname || ' (' || username || ')'); admin_role := wf_core.translate('WF_ADMIN_ROLE'); if (admin_mode = 'Y') then htp.p(' - ' || wf_core.translate('WF_ADMIN')); end if; htp.p('
'); */ -- Additional Message if (message is not null) then htp.p('
'); htp.p(message); end if; end if; if origin = 'FRAME' then htp.fontOpen(cface=>'ARIAL,HELVETICA',csize=>'-1'); end if; if origin = 'NORMAL' then wrklstbuf := ' ('|| to_char(wf_notification.WorkCount(username)) || ' ' || wf_core.translate('OPEN_NOTIFICATIONS') || ')'; htp.tableopen(calign=>'LEFT', cattributes=>'WIDTH=80% summary=""'); else -- dont print the "n open notifications" message next to Worklist -- because worklist will be displayed. wrklstbuf := ''; htp.tableopen(cattributes=>'summary=""'); end if; if (admin_mode = 'Y') then -- WorkList Event htp.tablerowopen; htp.tabledata(''||
             wf_core.translate('OPEN_NOTIFICATIONS')||''|| anchor_tag||owa_util.get_owa_service_path || 'wfa_html.WorkList?user='||username||'&'||'resetcookie=1>'|| wf_core.translate('WFA_WTITLE') || '
' || wrklstbuf, cattributes=>'id=""'); htp.tabledata(''||
             wf_core.translate('WFE_LIST_EVENTS_TITLE')||''|| anchor_tag||owa_util.get_owa_service_path || 'wf_event_html.listevents?resetcookie=T>' || wf_core.translate('WFE_LIST_EVENTS_TITLE')|| '', cattributes=>'id=""'); htp.tablerowclose; -- Find Notification Find Event htp.tablerowopen; htp.tabledata(''||
             wf_core.translate('WFA_FINDTITLE')||''|| anchor_tag||owa_util.get_owa_service_path || 'wfa_html.Find>' || wf_core.translate('WFA_FINDTITLE') || '', cattributes=>'id=""'); htp.tabledata(''||
             wf_core.translate('WFE_FIND_EVENT_TITLE')||''|| anchor_tag||owa_util.get_owa_service_path || 'wf_event_html.findevent>' || wf_core.translate('WFE_FIND_EVENT_TITLE')|| '', cattributes=>'id=""'); htp.tablerowclose; -- Find Route Systems htp.tablerowopen; htp.tabledata(''||
             wf_core.translate('WFRTG_LIST_TITLE')||''|| anchor_tag||owa_util.get_owa_service_path || 'wf_route.Find>' || wf_core.translate('WFRTG_FIND_TITLE') || '', cattributes=>'id=""'); htp.tabledata(''||
             wf_core.translate('WFE_LIST_SYSTEMS_TITLE')||''|| anchor_tag||owa_util.get_owa_service_path || 'wf_event_html.listsystems?resetcookie=T>' || wf_core.translate('WFE_LIST_SYSTEMS_TITLE')|| '', cattributes=>'id=""'); htp.tablerowclose; -- Find Process (Monitor) Find system htp.tablerowopen; htp.tabledata(''||
             wf_core.translate('WFMON_FINDTITLE')||''|| anchor_tag||owa_util.get_owa_service_path || 'wf_monitor.Find_Instance>' || wf_core.translate('WFMON_FINDTITLE') || '', cattributes=>'id=""'); htp.tabledata(''||
             wf_core.translate('WFE_FIND_SYSTEM_TITLE')||''|| anchor_tag||owa_util.get_owa_service_path || 'wf_event_html.findsystem>' || wf_core.translate('WFE_FIND_SYSTEM_TITLE')|| '', cattributes=>'id=""'); htp.tablerowclose; -- User Preference Agents htp.tablerowopen; htp.tabledata(''||
             wf_core.translate('WFPREF_EDIT_PREFS_TITLE')||''|| anchor_tag||owa_util.get_owa_service_path || 'wf_pref.edit>' || wf_core.translate('WFPREF_EDIT_PREFS_TITLE') || '', cattributes=>'id=""'); htp.tabledata(''||
             wf_core.translate('WFE_LIST_AGENTS_TITLE')||''|| anchor_tag||owa_util.get_owa_service_path || 'wf_event_html.listagents?resetcookie=T>' || wf_core.translate('WFE_LIST_AGENTS_TITLE')|| '', cattributes=>'id=""'); htp.tablerowclose; -- Global Perference Find Agent htp.tablerowopen; htp.tabledata(''||
             wf_core.translate('WFPREF_EDIT_DEF_PREFS_TITLE')||''|| anchor_tag||owa_util.get_owa_service_path || 'wf_pref.edit?edit_defaults=Y>' || wf_core.translate('WFPREF_EDIT_DEF_PREFS_TITLE') || '', cattributes=>'id=""'); htp.tabledata(''||
             wf_core.translate('WFE_FIND_AGENT_TITLE')||''|| anchor_tag||owa_util.get_owa_service_path || 'wf_event_html.findagent>' || wf_core.translate('WFE_FIND_AGENT_TITLE')|| '', cattributes=>'id=""'); htp.tablerowclose; -- Document Nodes Subscriptions htp.tablerowopen; htp.tabledata(''||
             wf_core.translate('WFDM_EDIT_NODE_TITLE')||''|| anchor_tag||owa_util.get_owa_service_path || 'fnd_document_management.dm_nodes_display>' || wf_core.translate('WFDM_EDIT_NODE_TITLE')|| '', cattributes=>'id=""'); htp.tabledata(''||
             wf_core.translate('WFE_LIST_SUBSC_TITLE')||''|| anchor_tag||owa_util.get_owa_service_path || 'wf_event_html.listsubscriptions?resetcookie=T>' || wf_core.translate('WFE_LIST_SUBSC_TITLE')|| '', cattributes=>'id=""'); htp.tablerowclose; -- Item Type Definition Find Subscriptions htp.tablerowopen; htp.tabledata(''||
             wf_core.translate('WFITD_ITEM_TYPE_DEFINITION')||''|| anchor_tag||owa_util.get_owa_service_path || 'wf_item_definition.find_item_type>' || wf_core.translate('WFITD_ITEM_TYPE_DEFINITION')|| '', cattributes=>'id=""'); htp.tabledata(''||
             wf_core.translate('WFE_FIND_SUBSC_TITLE')||''|| anchor_tag||owa_util.get_owa_service_path || 'wf_event_html.findsubscription>' || wf_core.translate('WFE_FIND_SUBSC_TITLE')|| '', cattributes=>'id=""'); htp.tablerowclose; -- Launch Process Raise Business Event htp.tablerowopen; htp.tabledata(''||
             wf_core.translate('WFINIT_ITEM_TYPE_TITLE')||''|| anchor_tag||owa_util.get_owa_service_path || 'wf_initiate.itemtype>' || wf_core.translate('WFINIT_ITEM_TYPE_TITLE')|| '', cattributes=>'id=""'); htp.tabledata(''||
             wf_core.translate('WFE_RAISE_EVENT_TITLE')||''|| anchor_tag||owa_util.get_owa_service_path || 'wf_event_html.entereventdetails?p_event_name=%>' || wf_core.translate('WFE_RAISE_EVENT_TITLE')|| '', cattributes=>'id=""'); -- bug 3855093 - Check setup menu not required -- htp.tabledata(''||
     --        wf_core.translate('WFE_CHECK_ALL_TITLE')||''|| -- anchor_tag||owa_util.get_owa_service_path || -- 'wf_setup.check_all>' || -- wf_core.translate('WFE_CHECK_ALL_TITLE')|| '', cattributes=>'id=""'); htp.tablerowclose; -- Demo System Signup htp.tablerowopen; htp.tabledata(''||
             wf_core.translate('WF_DEMO_MENU')||''|| anchor_tag||owa_util.get_owa_service_path || 'wf_demo.home>' || wf_core.translate('WF_DEMO_MENU')|| '', cattributes=>'id=""'); htp.tabledata(''||
             wf_core.translate('WFE_SYSTEM_SIGNUP_TITLE')||''|| anchor_tag||owa_util.get_owa_service_path || 'wf_event_html.entereventdetails?p_event_name=oracle.apps.wf.event.system.signup>' || wf_core.translate('WFE_SYSTEM_SIGNUP_TITLE')|| '', cattributes=>'id=""'); -- bug 3855093 - Check setup removed. Moved Raise Business Event one cell above -- htp.tabledata(''||
     --        wf_core.translate('WFE_RAISE_EVENT_TITLE')||''|| -- anchor_tag||owa_util.get_owa_service_path || -- 'wf_event_html.entereventdetails?p_event_name=%>' || -- wf_core.translate('WFE_RAISE_EVENT_TITLE')|| '', cattributes=>'id=""'); htp.tablerowclose; -- Get System Identifier htp.tablerowopen; htp.tabledata('', cattributes=>'id=""'); htp.tabledata(''||
             wf_core.translate('WFE_SYSTEM_IDENTIFIER_TITLE')||''|| anchor_tag||owa_util.get_owa_service_path || 'wf_event_html.getsystemidentifier>' || wf_core.translate('WFE_SYSTEM_IDENTIFIER_TITLE')|| '', cattributes=>'id=""'); -- bug 3855093 - Check setup removed. Moved System Signup one cell above -- htp.tabledata(''||
     --        wf_core.translate('WFE_SYSTEM_SIGNUP_TITLE')||''|| -- anchor_tag||owa_util.get_owa_service_path || -- 'wf_event_html.entereventdetails?p_event_name=oracle.apps.wf.event.system.signup>' || -- wf_core.translate('WFE_SYSTEM_SIGNUP_TITLE')|| '', cattributes=>'id=""'); htp.tablerowclose; -- Get System Identifier (moved above) -- htp.tablerowopen; -- htp.tabledata('', cattributes=>'id=""'); -- bug 3855093 - Check setup removed. Moved System Identifier one cell above -- htp.tabledata(''||
     --        wf_core.translate('WFE_SYSTEM_IDENTIFIER_TITLE')||''|| -- anchor_tag||owa_util.get_owa_service_path || -- 'wf_event_html.getsystemidentifier>' || -- wf_core.translate('WFE_SYSTEM_IDENTIFIER_TITLE')|| '', cattributes=>'id=""'); -- htp.tablerowclose; -- Standard Event Queues (Deprecated) -- htp.tablerowopen; -- htp.tabledata('', cattributes=>'id=""'); -- bug 3855093 - Event Queue Summary removed -- htp.tabledata(''||
     --        wf_core.translate('WFE_EVENT_QUEUE_SUMMARY_TITLE')||''|| -- anchor_tag||owa_util.get_owa_service_path || -- 'wf_event_html.eventqueuedisplay>' || -- wf_core.translate('WFE_EVENT_QUEUE_SUMMARY_TITLE')|| '', cattributes=>'id=""'); -- htp.tablerowclose; else -- Worklist htp.tablerowopen; htp.tabledata(''||
             wf_core.translate('OPEN_NOTIFICATIONS')||''|| anchor_tag||owa_util.get_owa_service_path || 'wfa_html.WorkList?resetcookie=1>'|| wf_core.translate('WFA_WTITLE') || '' || wrklstbuf, cattributes=>'id=""'); htp.tablerowclose; -- Find Notification htp.tablerowopen; htp.tabledata(''||
             wf_core.translate('WFA_FINDTITLE')||''|| anchor_tag||owa_util.get_owa_service_path || 'wfa_html.Find>' || wf_core.translate('WFA_FINDTITLE') || '', cattributes=>'id=""'); htp.tablerowclose; -- List Route htp.tablerowopen; htp.tabledata(''||
              wf_core.translate('WFRTG_LIST_TITLE')||''|| anchor_tag||owa_util.get_owa_service_path || 'wf_route.List>' || wf_core.translate('WFRTG_LIST_TITLE') || '', cattributes=>'id=""'); htp.tablerowclose; -- Find Process (Monitor) htp.tablerowopen; htp.tabledata(''||
             wf_core.translate('WFMON_FINDTITLE')||''|| anchor_tag||owa_util.get_owa_service_path || 'wf_monitor.Find_Instance>' || wf_core.translate('WFMON_FINDTITLE') || '', cattributes=>'id=""'); htp.tablerowclose; -- Personal Preference htp.tablerowopen; htp.tabledata(''||
             wf_core.translate('WFPREF_EDIT_PREFS_TITLE')||''|| anchor_tag||owa_util.get_owa_service_path || 'wf_pref.edit>' || wf_core.translate('WFPREF_EDIT_PREFS_TITLE') || '', cattributes=>'id=""'); htp.tablerowclose; end if; htp.tableclose; wfa_sec.Footer; htp.htmlClose; exception when others then rollback; wf_core.context('Wfa_Html', 'Homemenu'); wfa_html.Error; end Homemenu; procedure create_reg_button ( when_pressed_url IN VARCHAR2, onmouseover IN VARCHAR2, icon_top IN VARCHAR2, icon_name IN VARCHAR2, show_text IN VARCHAR2) IS onmouseover_text varchar2(240) := null; BEGIN htp.p(''); htp.p(''); htp.p(''); htp.p(''); htp.p(''); htp.p(''); htp.p(''); htp.p('
'); htp.p(''); htp.p(''); htp.p(''); htp.p('
'); htp.p(''); htp.p(''||show_text||'
'); exception when others then rollback; wf_core.context('Wfa_html', 'create_reg_button',when_pressed_url,onmouseover, icon_top,icon_name,show_text); wfa_html.Error; end create_reg_button; -- show_plsql_doc -- Show the content of a plsql document in a browser window -- Called from the related documents function procedure show_plsql_doc ( nid in number, aname in varchar2, nkey in varchar2) is username varchar2(320); clob_loc clob; blob_loc blob; clob_id number; clob_chunk number := 0; doctext varchar2(32000); end_of_text boolean :=FALSE; attr_name varchar2(30); slash pls_integer; wfsession varchar2(240); doctype varchar2(1000); lobsize number; amount number; l_enpos pls_integer; l_copos pls_integer; l_encoding varchar2(100); begin -- Check current user has admin authority if (nkey is null) then wfa_sec.GetSession(username); else -- copy this from wfa_html.authenticate slash := instr(nkey, '/'); if (slash <> 0) then wfsession := to_char(nid)||'/'||substr(nkey, slash+1); else wfsession := to_char(nid)||'/'||nkey; end if; username := Wf_Notification.AccessCheck(wfsession); if (username is null) then wf_core.raise('WFNTF_ACCESS_KEY'); end if; end if; username := upper(username); -- note that GetAttrDoc will not translate for PLSQLCLOB doctext := wf_notification.getattrdoc(nid, aname,wf_notification.doc_html); -- if the attribute wasn't translated then try to translate for plsqlclobs. if doctext = '&'||aname then dbms_lob.createTemporary(clob_loc, false, dbms_lob.call); Wf_Notification.GetAttrCLOB(nid, aname, wf_notification.doc_html, clob_loc, doctype, attr_name); -- We have the document. Now determine the output method. -- HTML documents can be output as they are. -- Binary documents can only be downloaded if doctype in (wf_notification.doc_text, wf_notification.doc_html) then -- HTML or text document. htp.htmlOpen; htp.headOpen; htp.p(''); htp.title(wf_core.translate('WFITD_ATTR_TYPE_DOCUMENT')); wfa_html.create_help_function('wfnew/wfnew52.htm#nrr'); htp.headClose; wfa_sec.Header(FALSE, '',wf_core.translate('WFITD_ATTR_TYPE_DOCUMENT'), TRUE); htp.br; lobsize := dbms_lob.getlength(clob_loc); amount := 32000; wf_notification.clob_chunk := 0; while not (end_of_text) loop wf_notification.readattrclob(nid, aname, doctext, end_of_text); htp.prn(doctext); end loop; wfa_sec.Footer; htp.htmlClose; elsif attr_name is not null then -- BINARY Document l_enpos := instr(upper(doctype), 'ENCODING=', 1); if (l_enpos > 0) then l_enpos := l_enpos + length('ENCODING='); l_copos := instr(doctype, ';', l_enpos); if (l_copos > 0) then l_encoding := substr(doctype, l_enpos, (l_copos-l_enpos)); else l_encoding := substr(doctype, l_enpos); end if; -- Decode base64 encoded content if (upper(trim(l_encoding)) = 'BASE64') then dbms_lob.createTemporary(blob_loc, FALSE, dbms_lob.call); wf_mail_util.decodeBLOB(clob_loc, blob_loc); owa_util.mime_header(doctype, FALSE); htp.p( 'Content-length: ' || dbms_lob.getlength(blob_loc)); owa_util.http_header_close; wpg_docload.download_file(blob_loc); dbms_lob.freeTemporary(blob_loc); end if; else -- This provides limited binary document support. -- It assumes that the document in stored as raw in varchar. owa_util.mime_header(doctype, TRUE); lobsize := dbms_lob.getlength(clob_loc); amount := 32000; wf_notification.clob_chunk := 0; while not (end_of_text) loop wf_notification.readattrclob(nid, aname, doctext, end_of_text); htp.p(doctext); end loop; end if; else -- attr_name is null try for a PLSQLBLOB document dbms_lob.createTemporary(blob_loc, false, dbms_lob.call); Wf_Notification.GetAttrBLOB(nid, aname, wf_notification.doc_html, blob_loc, doctype, attr_name); owa_util.mime_header(doctype, FALSE); htp.p( 'Content-length: ' || dbms_lob.getlength(blob_loc)); owa_util.http_header_close; wpg_docload.download_file(blob_loc); dbms_lob.freeTemporary(blob_loc); end if; else -- Set page title htp.htmlOpen; htp.headOpen; htp.title(wf_core.translate('WFITD_ATTR_TYPE_DOCUMENT')); wfa_html.create_help_function('wfnew/wfnew52.htm#nrr'); htp.headClose; wfa_sec.Header(FALSE, '',wf_core.translate('WFITD_ATTR_TYPE_DOCUMENT'), TRUE); htp.br; htp.p (doctext); wfa_sec.Footer; htp.htmlClose; end if; exception when others then wf_core.context('Wfa_Html','show_plsql_doc',nid, aname); wfa_html.Error; end show_plsql_doc; -- base_url -- Get the base url for the current browser where you have launched the -- login for Workflow function base_url (get_from_resources BOOLEAN) return varchar2 IS l_base_url VARCHAR2(2000) := NULL; BEGIN BEGIN IF (get_from_resources = FALSE) THEN -- Need to strip off trailing / to match wf_web_agent format l_base_url := SUBSTR(RTRIM(owa_util.get_owa_service_path), 1, LENGTH(RTRIM(owa_util.get_owa_service_path)) - 1); ELSE l_base_url := wf_core.translate ('WF_WEB_AGENT'); END IF; EXCEPTION WHEN OTHERS THEN l_base_url := wf_core.translate ('WF_WEB_AGENT'); END; return (l_base_url); exception when others then wf_core.context('Wfa_Html','base_url'); wfa_html.Error; end base_url; -- -- wf_user_val -- Create the lov content for our user lov. This function -- is called by the generic lov function -- IN -- RETURNS -- procedure wf_user_val ( p_mode in varchar2, p_lov_name in varchar2, p_start_row in number, p_max_rows in number, p_hidden_value in out nocopy varchar2, p_display_value in out nocopy varchar2, p_result out nocopy number) IS CURSOR c_user_lov (c_find_criteria IN VARCHAR2) IS SELECT name, display_name FROM wf_roles where status <> 'INACTIVE' and (UPPER(display_name) LIKE UPPER(c_find_criteria)||'%' and (display_name LIKE LOWER(SUBSTR(c_find_criteria, 1, 2))||'%' or display_name LIKE LOWER(SUBSTR(c_find_criteria, 1, 1))|| UPPER(SUBSTR(c_find_criteria, 2, 1))||'%' or display_name LIKE INITCAP(SUBSTR(c_find_criteria, 1, 2))||'%' or display_name LIKE UPPER(SUBSTR(c_find_criteria, 1, 2))||'%')) or (orig_system not in ('HZ_PARTY','POS','ENG_LIST','AMV_CHN', 'HZ_GROUP','CUST_CONT') and UPPER(name) LIKE UPPER(c_find_criteria)||'%' and (name LIKE LOWER(SUBSTR(c_find_criteria, 1, 2))||'%' or name LIKE LOWER(SUBSTR(c_find_criteria, 1, 1))|| UPPER(SUBSTR(c_find_criteria, 2, 1))||'%' or name LIKE INITCAP(SUBSTR(c_find_criteria, 1, 2))||'%' or name LIKE UPPER(SUBSTR(c_find_criteria, 1, 2))||'%')) and status <> 'INACTIVE' order by display_name; -- Added additional where condition "status <> 'INACTIVE' so only ACTIVE -- roles display -- CURSOR c_user_display_value (c_name IN VARCHAR2) IS -- select name, display_name -- from wf_roles -- where name = c_name; ii NUMBER := 0; nn NUMBER := 0; l_total_rows NUMBER := 0; l_id NUMBER; l_name VARCHAR2 (320); -- enlarged from 30 to match db definition l_display_name VARCHAR2 (360); -- enlarged from 80 to match db definition l_result NUMBER := 1; -- This is the return value for each mode colon NUMBER; role_info_tbl wf_directory.wf_local_roles_tbl_type; BEGIN if (p_mode = 'LOV') then /* ** Need to get a count on the number of rows that will meet the ** criteria before actually executing the fetch to show the user ** how many matches are available. */ select count(*) into l_total_rows FROM wf_roles where status <> 'INACTIVE' and (UPPER(display_name) LIKE UPPER(p_display_value)||'%' and (display_name LIKE LOWER(SUBSTR(p_display_value, 1, 2))||'%' or display_name LIKE LOWER(SUBSTR(p_display_value, 1, 1))|| UPPER(SUBSTR(p_display_value, 2, 1))||'%' or display_name LIKE INITCAP(SUBSTR(p_display_value, 1, 2))||'%' or display_name LIKE UPPER(SUBSTR(p_display_value, 1, 2))||'%')) or (orig_system not in ('HZ_PARTY','POS','ENG_LIST','AMV_CHN', 'HZ_GROUP','CUST_CONT') and UPPER(name) LIKE UPPER(p_display_value)||'%' and (name LIKE LOWER(SUBSTR(p_display_value, 1, 2))||'%' or name LIKE LOWER(SUBSTR(p_display_value, 1, 1))|| UPPER(SUBSTR(p_display_value, 2, 1))||'%' or name LIKE INITCAP(SUBSTR(p_display_value, 1, 2))||'%' or name LIKE UPPER(SUBSTR(p_display_value, 1, 2))||'%')) and status <> 'INACTIVE'; wf_lov.g_define_rec.total_rows := l_total_rows; wf_lov.g_define_rec.add_attr1_title := wf_core.translate ('WFITD_INTERNAL_NAME'); open c_user_lov (p_display_value); LOOP FETCH c_user_lov INTO l_name, l_display_name; EXIT WHEN c_user_lov%NOTFOUND OR nn >= p_max_rows; ii := ii + 1; IF (ii >= p_start_row) THEN nn := nn + 1; wf_lov.g_value_tbl(nn).hidden_key := l_name; wf_lov.g_value_tbl(nn).display_value := l_display_name; wf_lov.g_value_tbl(nn).add_attr1_value := l_name; END IF; END LOOP; l_result := 1; elsif (p_mode = 'GET_DISPLAY_VAL') THEN Wf_Directory.GetRoleInfo2(p_hidden_value,role_info_tbl); l_name := role_info_tbl(1).name; l_display_name := role_info_tbl(1).display_name; p_display_value:= l_name; l_result := 1; elsif (p_mode = 'VALIDATE') THEN /* ** If mode = VALIDATE then see how many rows match the criteria ** If its 0 then thats not good. Raise an error and tell them to use LOV ** If its 1 then thats great. ** If its more than 1 then check to see if they used the LOV to select ** the value */ open c_user_lov (p_display_value); LOOP FETCH c_user_lov INTO l_name, l_display_name; EXIT WHEN c_user_lov%NOTFOUND OR ii = 2; ii := ii + 1; p_hidden_value := l_name; END LOOP; /* ** If ii=0 then no rows were found and you have an error in the value ** entered so present a no rows found and use the lov icon to select ** value ** If ii=1 then one row is found then you've got the right value ** If ii=2 then more than one row was found so check to see if the display ** value taht was selected is not unique in the LOV (Person Name) and ** that the LOV was used so the Hidden value has been set to a unique ** value. If it comes up with more than 1 in this case then present ** the please use lov icon to select value. */ if (ii = 2) then -- copy logic from wf_directory.getroleinfo2 colon := instr(p_display_value,':'); if (colon = 0) then select count(*) into ii from WF_ROLES where NAME = p_display_value and ORIG_SYSTEM not in ('HZ_PARTY','POS','ENG_LIST','AMV_CHN', 'HZ_GROUP','CUST_CONT'); else select count(*) into ii from WF_ROLES where NAME = p_display_value and ORIG_SYSTEM = substr(p_display_value, 1, colon-1) and ORIG_SYSTEM_ID = substr(p_display_value, colon+1); end if; END IF; l_result := ii; end if; p_result := l_result; exception when others then rollback; wf_core.context('Wfa_Html', 'wf_user_val'); raise; end wf_user_val; function replace_onMouseOver_quotes(p_string in varchar2) return varchar2 is temp_string varchar2(2000); c_browser varchar2(400) := owa_util.get_cgi_env('HTTP_USER_AGENT'); begin -- replace single quotes temp_string := replace(p_string,'''','\'''); -- replace double quotes if (instr(c_browser, 'MSIE') <> 0) then temp_string := replace(temp_string,'"','\'''); else temp_string := replace(temp_string,'"','`"'); end if; -- check for double escapes temp_string := replace(temp_string,'\\','\'); return temp_string; end replace_onMouseOver_quotes; procedure validate_display_name ( p_display_name in varchar2, p_user_name in out nocopy varchar2) IS l_colon NUMBER := 0; l_names_count NUMBER := 0; l_name VARCHAR2(320); l_upper_name VARCHAR2(360); l_orig_system_id NUMBER; l_get_role BOOLEAN := TRUE; role_info_tbl wf_directory.wf_local_roles_tbl_type; BEGIN /* ** Make sure to blank out the internal name if the user originally ** used the LOV to select the name and then blanked out the display ** name then make sure here to blank out the insternal name and return */ if (p_display_name is null) then p_user_name := NULL; return; end if; /* ** Bug# 2236250 validating the display name to contain a valid number ** after the colon to be used as a internal name for the role */ l_colon := instr(p_display_name, ':'); if (l_colon > 0) then begin l_orig_system_id := to_number(substr(p_display_name, l_colon+1)); exception when invalid_number then l_get_role := FALSE; when others then raise; end; l_colon := 0; end if; /* ** First look first for internal name to see if you find a match. If ** there are duplicate internal names that match the criteria then ** there is a problem with directory services but what can you do. Go ** ahead and pick the first name so you return something ** ** Bug# 2236250 calling Wf_Directory.GetRoleInfo2 only if the value ** after ':' is numeric. */ if (l_get_role) then l_upper_name := upper(p_display_name); Wf_Directory.GetRoleInfo2(l_upper_name,role_info_tbl); l_name := role_info_tbl(1).name; end if; /* ** If you found a match on internal name then set the p_user_name ** accordingly. */ if (l_name IS NOT NULL) then p_user_name := l_name; /* ** If there was no match on internal name then check for a display ** name */ else /* ** Check out how many names match the display name */ select count(1) into l_names_count from wf_roles where display_name = p_display_name; /* ** If there are no matches for the display name then raise an error */ if (l_names_count = 0) then -- Not displayed or internal role name, error wf_core.token('ROLE', p_display_name); wf_core.raise('WFNTF_ROLE'); /* ** If there is just one match then get the internal name ** and assign it. */ elsif (l_names_count = 1) then select name into l_name from wf_roles where display_name = p_display_name; p_user_name := l_name; /* ** If there is more than one match then see if the user ** used the lov to select the name in which case the combination ** of the display name and the user name should be unique */ else -- copy logic from wf_directory.getroleinfo2 l_colon := instr(p_user_name,':'); if (l_colon = 0) then select count(1) into l_names_count from WF_ROLES where NAME = p_user_name and ORIG_SYSTEM not in ('HZ_PARTY','POS','ENG_LIST','AMV_CHN', 'HZ_GROUP','CUST_CONT') and DISPLAY_NAME = p_display_name; else /* ** Bug# 2236250 validate if the value after ':' is number ** before using it in the query */ begin l_orig_system_id := to_number(substr(p_user_name, l_colon+1)); exception when invalid_number then wf_core.raise('WFNTF_ORIGSYSTEMID'); when others then raise; end; select count(1) into l_names_count from WF_ROLES where NAME = p_user_name and ORIG_SYSTEM = substr(p_user_name, 1, l_colon-1) and ORIG_SYSTEM_ID = l_orig_system_id and DISPLAY_NAME = p_display_name; end if; if (l_names_count <> 1) then wf_core.token('ROLE', p_display_name); wf_core.raise('WFNTF_UNIQUE_ROLE'); end if; end if; end if; exception when others then wf_core.context('Wfa_Html', 'validate_display_name', p_display_name, p_user_name); raise; end validate_display_name; -- LongDesc -- Displays an html page with the token message. This is called from -- frames for the LONGDESC attribute. procedure LongDesc (p_token in varchar2) as BEGIN htp.htmlOpen; htp.headOpen; htp.title(wf_core.translate('LONG_DESC')); htp.headClose; begin wfa_sec.Header(background_only=>TRUE); exception when others then htp.bodyOpen; end; htp.p(WF_CORE.Translate(UPPER(p_token))); wfa_sec.Footer; htp.htmlClose; END LongDesc; end WFA_HTML; / commit; create or replace package body WFA_HTML_UTIL as /* $Header: wfhtmb.pls 26.64 2005/03/11 06:18:55 anachatt ship $ */ -- -- Package Globals -- result_button_threshold pls_integer := 3; -- Max number of submit buttons -- -- GetUrl (PRIVATE) -- Produce URL link in response portion -- IN -- nid - -- description - instructions -- value - url string not token substituted procedure GetUrl( nid in number, description in varchar2, value in varchar2) as urlstring varchar2(1950); begin -- Ignore if no URL provided if (value is null) then return; end if; htp.tableRowOpen; -- Include description if needed. -- NOTE: Description are printed here instead of in the prompt link -- as for other fields, because the prompt is already used for the -- URL itself. if (description is not null) then htp.tableData(description, 'right', cattributes=>'id=""'); else htp.tableData(htf.br, cattributes=>'id=""'); end if; -- Print URL urlstring:=wf_notification.GetURLText(value, nid); htp.p(' '||urlstring||''); htp.tableRowClose; exception when others then wf_core.context('Wfa_Html_Util', 'GetUrl', value, description, to_char(nid)); raise; end GetUrl; -- -- GetField (PRIVATE) -- Produce a varchar2/number/date response field -- IN -- name - field name -- type - field type (VARCHAR2, NUMBER, DATE) -- format - format mask -- dvalue - default value -- index - the attribute element number in the attribute list -- procedure GetField( name in varchar2, type in varchar2, format in varchar2, dvalue in varchar2, index_num in number, nid in number, nkey in varchar2) is len pls_integer; l_url varchar2(1000); l_media varchar2(240) := wfa_html.image_loc; l_icon varchar2(30) := 'FNDILOV.gif'; l_username varchar2(320); -- Username to query l_document_name Varchar2(240) := NULL; l_callback_URL varchar2(4000); l_attach_URL varchar2(4000); l_document_attributes fnd_document_management.fnd_document_attributes; l_message varchar2(400) := NULL; slash pls_integer; wfsession varchar2(240); begin -- Figure field len if (type = 'VARCHAR2') then len := nvl(to_number(format), 2000); else len := 62; end if; -- Draw field htp.formHidden('h_fnames', name||'#'||type||'#'||format); /* Need to create a hidden document name field if this is not a document ** resond attrubute, otherwise the index will reference index elements ** that don't exist because the element lists are out of sync */ if (type NOT IN ('DOCUMENT' , 'ROLE')) THEN htp.formHidden('h_fdocnames', ''); end if; if (len <= 80) then /* ** If this is a document field then hide the actual h_fvalue field ** Since this will store the document info that gets passed to the ** document attribute. You then need to create a name field so the ** user can see what they've selected. */ if (type = 'DOCUMENT') THEN htp.formhidden ('h_fvalues', dvalue); -- Set the destination field name for the document id fnd_document_management.set_document_id_html ( 'bottom', 'WFNOTRESP', 'h_fvalues['||index_num||']', 'h_fdocnames['||index_num||']', l_callback_url); -- Check session and current user if (nkey is null) then wfa_sec.GetSession(l_username); else -- copy this from wfa_html.authenticate slash := instr(nkey, '/'); if (slash <> 0) then wfsession := to_char(nid)||'/'||substr(nkey, slash+1); else wfsession := to_char(nid)||'/'||nkey; end if; l_username := Wf_Notification.AccessCheck(wfsession); if (l_username is null) then wf_core.raise('WFNTF_ACCESS_KEY'); end if; end if; l_username := upper(l_username); fnd_document_management.get_launch_attach_url ( l_username, l_callback_url, TRUE, l_attach_url); /* ** If the default value is a dm document then go get the ** title from the DM system and place it in the field. If ** its a plsql doc then just put the default value in the field */ IF (SUBSTR(dvalue, 1, 3) = 'DM:') THEN /* ** get the document name */ fnd_document_management.get_document_attributes(l_username, dvalue, l_document_attributes); l_document_name := l_document_attributes.document_name; ELSE l_document_name := dvalue; END IF; -- document field htp.tableData( cvalue=>htf.formText(cname=>'h_fdocnames', csize=>len-30, cmaxlength=>len, cvalue=>l_document_name)|| '   '|| l_attach_URL, calign=>'Left', cattributes=>'id=""'); else -- single line field -- htp.tableData( -- cvalue=>htf.formText(cname=>'h_fvalues', csize=>len, -- cmaxlength=>len, cvalue=>dvalue), -- calign=>'Left'); htp.p(''); if (type <> 'ROLE') then htp.formText(cname=>'h_fvalues', csize=>len, cmaxlength=>len, cvalue=>dvalue); else l_message := wf_core.translate ('WFPREF_LOV'); htp.formhidden ('h_fvalues', dvalue); -- add LOV here: Note:bottom is name of frame. -- Note: The REPLACE function replaces all the space characters with -- the proper escape sequence. l_url := 'javascript:fnd_open_dm_display_window('||''''|| REPLACE('wf_lov.display_lov?p_lov_name='||'owner'|| '&p_display_name='||'WFA_FIND_USER'|| '&p_validation_callback=wfa_html.wf_user_val'|| '&p_dest_hidden_field=top.opener.parent.bottom.document.WFNOTRESP.h_fvalues['||to_char(index_num)||'].value'|| '&p_current_value=top.opener.parent.bottom.document.WFNOTRESP.h_fdocnames['||to_char(index_num)||'].value'|| '&p_display_key='||'Y'|| '&p_dest_display_field=top.opener.parent.bottom.document.WFNOTRESP.h_fdocnames['||to_char(index_num)||'].value', ' ', '%20')||''''||',500,500)'; -- print everything together so ther is no gap. htp.p(htf.formText(cname=>'h_fdocnames', csize=>len, cmaxlength=>240, cvalue=>dvalue)|| ''|| ''||
                    l_message||''); end if; htp.p(''); end if; else -- multi line field htp.tableData( cvalue=>htf.formTextareaOpen2( cname=>'h_fvalues', nrows=>2, ncolumns=>65, cwrap=>'SOFT', cattributes=>'maxlength='||to_char(len))|| dvalue|| htf.formTextareaClose, calign=>'Left', cattributes=>'id=""'); end if; exception when others then wf_core.context('Wfa_Html_Util', 'GetField', name, type, format, dvalue); raise; end GetField; -- -- GetLookup (PRIVATE) -- Produce a lookup response field -- IN -- name - field name -- value - default value (lookup code) -- format - lookup type -- submit - flag include a submit button for result field -- procedure GetLookup( name in varchar2, value in varchar2, format in varchar2, submit in boolean) as cursor lookup_codes(p_lookup_type varchar2) is select MEANING, LOOKUP_CODE from WF_LOOKUPS where LOOKUP_TYPE = p_lookup_type order by MEANING; template varchar2(4000); begin -- Create hidden field and select list template := htf.formHidden('h_fnames', name||'#LOOKUP#'||format)|| wf_core.newline|| htf.formSelectOpen('h_fvalues'); -- Add all lookups to select list for i in lookup_codes(format) loop if (i.lookup_code = value) then template := template||wf_core.newline|| htf.formSelectOption(i.meaning, 'SELECTED','VALUE="'||i.lookup_code||'"'); else template := template||wf_core.newline|| htf.formSelectOption(i.meaning,null,'VALUE="'||i.lookup_code||'"'); end if; end loop; template := template||wf_core.newline||htf.formSelectClose; if (not submit) then -- Draw a normal field htp.tableData(template, 'left', cattributes=>'id=""'); htp.formHidden('h_fdocnames', ''); else -- Draw a submit-style field for the result. -- Leave TableData open so reassign button can be added to same cell. htp.p(''||wf_core.newline||template||''); htp.p(''); wfa_html.create_reg_button ('javascript:document.WFNOTRESP.submit()', wf_core.translate ('SUBMIT'), wfa_html.image_loc, null, wf_core.translate ('SUBMIT')); htp.p(''); end if; exception when others then wf_core.context('Wfa_Html_Util', 'GetLookup', name, value, format); raise; end GetLookup; -- -- GetButtons (PRIVATE) -- Produce a response field as submit buttons -- IN -- value - default value -- format - lookup type -- procedure GetButtons( value in varchar2, format in varchar2, otherattr in number) as respcnt pls_integer; indexer number := otherattr; cursor lookup_codes(p_lookup_type varchar2) is select MEANING, LOOKUP_CODE from WF_LOOKUPS where LOOKUP_TYPE = p_lookup_type order by MEANING; begin -- Check number of response values. begin select count(1) into respcnt from WF_LOOKUPS where LOOKUP_TYPE = format; exception when no_data_found then return; end; if (respcnt > wfa_html_util.result_button_threshold) then -- If number of responses over threshold use a select list instead. wfa_html_util.GetLookup('RESULT', value, format, TRUE); else -- Use buttons. -- Add a hidden field for the result field name htp.formHidden('h_fnames', 'RESULT#LOOKUP#'||format); htp.formHidden('h_fvalues', null); -- Add a button for every lookup for i in lookup_codes(format) loop htp.p(''); wfa_html.create_reg_button ('javascript:document.WFNOTRESP.h_fvalues['|| TO_CHAR(indexer)||'].value='|| ''''||i.lookup_code||''''||';document.WFNOTRESP.submit()', i.meaning, wfa_html.image_loc, null, i.meaning); htp.p(''); /*htp.formSubmit('h_fvalues', i.meaning, 'NOBORDER');*/ end loop; end if; exception when others then wf_core.context('Wfa_Html_Util', 'GetButtons', value, format); raise; end GetButtons; -- -- SetAttribute (PRIVATE) -- Set response attributes when processing a response. -- IN -- nid - notification id -- attr_name_type - attribute name#type#format -- attr_value - attribute value -- procedure SetAttribute( nid in number, attr_name_type in varchar2, attr_value in varchar2, doc_name in varchar2) as first pls_integer; second pls_integer; attr_type varchar2(8); attr_name varchar2(30); attr_fmt varchar2(240); lovcode varchar2(30); l_attr_value varchar2(30); begin -- Parse out name#type#format first := instr(attr_name_type, '#', 1); second := instr(attr_name_type, '#', 1, 2); attr_name := substr(attr_name_type, 1, first-1); attr_type := substr(attr_name_type, first+1, second-first-1); attr_fmt := substr(attr_name_type, second+1, length(attr_name_type)-second); if (attr_type = 'DATE') then if (attr_fmt is not null) then wf_notification.SetAttrDate(nid, attr_name, to_date(attr_value, attr_fmt)); else wf_notification.SetAttrDate(nid, attr_name, to_date(attr_value)); end if; elsif (attr_type = 'NUMBER') then if (attr_fmt is not null) then wf_notification.SetAttrNumber(nid, attr_name, to_number(attr_value, attr_fmt)); else wf_notification.SetAttrNumber(nid, attr_name, to_number(attr_value)); end if; elsif (attr_type = 'ROLE') then /* ** If this is a role then try to get the unique role name for the ** user that was selected. Since this could be a display name ** or an internal name, make sure to get the unique internal name */ l_attr_value := attr_value; wfa_html.validate_display_name (doc_name, l_attr_value); -- -- Set the role to upper -- wf_notification.SetAttrText(nid, attr_name, l_attr_value); elsif (attr_type = 'DOCUMENT') then -- if PLSQL then use the display value into which the user typed if upper(substr(doc_name,1, 5)) = 'PLSQL' then wf_notification.SetAttrText(nid, attr_name, doc_name); -- use the hidden field populated by doc lov else wf_notification.SetAttrText(nid, attr_name, attr_value); end if; else -- VARCHAR2 or LOOKUP or misc value wf_notification.SetAttrText(nid, attr_name, attr_value); end if; exception when others then wf_core.context('Wfa_Html_Util', 'SetAttribute', to_char(nid), attr_name_type, attr_value); raise; end SetAttribute; -- -- GetLookupMeaning (PRIVATE) -- Retrieve displayed value of lookup -- IN -- ltype - lookup type -- lcode - lookup code -- RETURNS -- Displayed meaning of lookup code -- function GetLookupMeaning( ltype in varchar2, lcode in varchar2) return varchar2 is meaning varchar2(80); begin select WL.MEANING into meaning from WF_LOOKUPS WL where WL.LOOKUP_TYPE = GetLookupMeaning.ltype and WL.LOOKUP_CODE = GetLookupMeaning.lcode; return(meaning); exception when no_data_found then return(lcode); when others then wf_core.context('Wfa_Html_Util', 'GetLookupMeaning', ltype, lcode); raise; end GetLookupMeaning; -- -- GetUrlCount (PRIVATE) -- IN -- nid - notification id -- OUT -- urlcnt - number of urls as reponse attributes -- urlstrg - one of the urls if it exist -- this is generally discarded unless there is only one procedure GetUrlCount( nid in number, urlcnt out nocopy number, urlstrg out nocopy varchar2) is buf pls_integer; begin select count(1),max(NA.TEXT_VALUE) into urlcnt, urlstrg from WF_NOTIFICATION_ATTRIBUTES NA, WF_MESSAGE_ATTRIBUTES MA, WF_NOTIFICATIONS N where N.NOTIFICATION_ID = nid and NA.NOTIFICATION_ID = N.NOTIFICATION_ID and MA.MESSAGE_NAME = N.MESSAGE_NAME and MA.MESSAGE_TYPE = N.MESSAGE_TYPE and MA.NAME = NA.NAME and MA.SUBTYPE = 'RESPOND' and MA.TYPE = 'URL'; exception when others then wf_core.context('Wfa_Html_Util', 'GetUrlCount', to_char(nid)); raise; end GetUrlCount; -- -- GetResponseUrl (PRIVATE) -- Return single response url. -- NOTE: this assumes there is exactly one response url attribute. -- IN -- nid - notification id -- RETURNS -- Response url -- function GetResponseUrl( nid in number) return varchar2 is buf varchar2(4000); begin select text_value into buf from WF_NOTIFICATION_ATTRIBUTES NA, WF_MESSAGE_ATTRIBUTES_VL MA, WF_NOTIFICATIONS N where N.NOTIFICATION_ID = nid and NA.NOTIFICATION_ID = N.NOTIFICATION_ID and MA.MESSAGE_NAME = N.MESSAGE_NAME and MA.MESSAGE_TYPE = N.MESSAGE_TYPE and MA.NAME = NA.NAME and MA.SUBTYPE = 'RESPOND' and MA.TYPE = 'URL' and ROWNUM = 1; return(buf); exception when others then wf_core.context('Wfa_Html_Util', 'GetResponseUrl', to_char(nid)); raise; end GetResponseUrl; -- -- GetDisplayValue (PRIVATE) -- Get displayed value of a response field -- IN -- type - field type (VARCHAR2, NUMBER, DATE, LOOKUP, URL) -- format - field format (depends on type) -- tvalue - text value -- nvalue - number value -- dvalue - date value -- RETURNS -- Displayed value -- function GetDisplayValue( type in varchar2, format in varchar2, tvalue in varchar2, nvalue in number, dvalue in date) return varchar2 is s0 varchar2(2000); value varchar2(4000); begin if (type = 'VARCHAR2') then value := tvalue; elsif (type = 'NUMBER') then if (format is null) then value := to_char(nvalue); else value := to_char(nvalue, format); end if; elsif (type = 'DATE') then if (format is null) then value := to_char(dvalue); else value := to_char(dvalue, format); end if; elsif (type = 'LOOKUP') then value := wfa_html_util.GetLookupMeaning(format, tvalue); elsif (type = 'URL') then value := tvalue; elsif (type = 'ROLE') then wf_directory.GetRoleInfo(tvalue, value, s0, s0, s0, s0); else -- Default to return text value unchanged value := tvalue; end if; return(value); exception when others then wf_core.context('Wfa_Html_Util', 'GetDisplayWindow', type, format, tvalue, to_char(nvalue), to_char(dvalue)); raise; end GetDisplayValue; -- -- GetDenormalizedValues -- Populate WF_NOTIFICATIONS with the needed values with supplied langcode. -- Then returns those values via the out variables. -- IN: -- nid - notification id -- langcode - language code -- OUT: -- from_user - display name of from role -- to_user - display name of recipient_role -- subject - subject of the notification -- procedure GetDenormalizedValues(nid in number, langcode in varchar2, from_user out nocopy varchar2, to_user out nocopy varchar2, subject out nocopy varchar2) is begin Wf_Notification.Denormalize_Notification(nid=>nid,langcode=>langcode); begin select FROM_USER, TO_USER, SUBJECT into from_user, to_user, subject from WF_NOTIFICATIONS where NOTIFICATION_ID = nid; exception when OTHERS then from_user := null; to_user := null; subject := null; end; exception when OTHERS then wf_core.context('Wfa_Html_Util', 'GetDenormalizedValues', to_char(nid), langcode); raise; end GetDenormalizedValues; end WFA_HTML_UTIL; / commit; exit;