• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Developing A Real World Logistic Application With Oracle Application - UKOUG 2008
 

Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

on

  • 6,582 views

 

Statistics

Views

Total Views
6,582
Views on SlideShare
6,425
Embed Views
157

Actions

Likes
6
Downloads
126
Comments
0

12 Embeds 157

http://roelhartman.blogspot.com 74
http://www.slideshare.net 25
http://www.apexblogs.info 25
http://www.ukocn.com 16
http://apexblogs.info 7
http://static.slideshare.net 3
http://roelhartman.blogspot.be 2
http://feeds2.feedburner.com 1
http://www.lmodules.com 1
http://www.linkedin.com 1
http://roelhartman.blogspot.nl 1
http://roelhartman.blogspot.kr 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • 6. Juni 2009 | Title of Presentation 0:01 / 0:01 Set expectations: What is it NOT about? NOT about Logistics NOT about APEX Architecture NOT about Interactive Reports or Charts What is this presentation about? Possibilities of building real Rich Internet Applications with APEX From ‘standard’ APEX behaviour to ‘Forms like’ APEX behaviour For Whom? Developers Technical (management) staff Who’s in the room? Experience with APEX? Experience with Forms?

Developing A Real World Logistic Application With Oracle Application - UKOUG 2008 Developing A Real World Logistic Application With Oracle Application - UKOUG 2008 Presentation Transcript

  • Developing a Real-World Logistic Application with Oracle Application Express Roel Hartman Software Architect / NL Lead Technical Architect Oracle
  • Agenda UKOUG 2008 04-12-2008 Introduction The Case Conclusions & Tips Q&A
  • Introduction 04-12-2008 UKOUG 2008 www.BloggingAboutOracle.org roelhartman.blogspot.com
  • Introduction Logica (a word from our sponsors)
      • A major international force in IT services and wireless telecoms with a leading position in Europe
      • Around 40,000 staff
      • Operating in over 40 countries
      • Around £3 billion revenues
      • One of the largest Oracle consultancies in Europe (> 2500)
      • One of the largest Oracle consultancies in The Netherlands (> 500)
    No. 04-12-2008 UKOUG 2008
  • Introduction Logica (another word from our sponsors)
      • We help leading organisations worldwide achieve their business objectives through the innovative delivery of information technology and business process solutions
      • We provide management and IT consultancy, design, systems integration, products, outsourcing and training to clients across markets including telecoms, financial services, energy and utilities, industry, distribution and transport and the public sector
      • Our main differentiators:
        • Full service provision
        • Deep industry knowledge
        • Value-added, mission-critical, repeatable, global offerings
        • Strong relationships (customers, partners, suppliers, staff)
        • A track record for delivering innovative solutions that provide real business benefit to our clients
    No. 04-12-2008 UKOUG 2008
  • The Client
      • International Bulk Logistic Solution Provider
      • Chemical, Food, Gas, Oil, Equipment
      • Europe, America, Asia
    No. 04-12-2008 UKOUG 2008
  • The Architecture No. 04-12-2008 UKOUG 2008 Accounts Payable/ Accounts Receivable administration Internet Board computer software TMS Planning software Supply C hain Ma n a g emen t Traffic information Order acceptance and processing Communication manager Onboard computer E Supply chain m anagement Mob ile internet Navigati on system
  • The Application
      • Oracle database
      • Client Server
      • Citrix
    No. 04-12-2008 UKOUG 2008
  • The Technical Environment No. 04-12-2008 UKOUG 2008 Oracle DB Definition Files
    • Fat database
    • Decreasing supplier support
    • Decreasing knowledge of the tool
    • Tool has its limitations
    • Users are satisfied with the UI (or got used to it)
    Application Processor Cache Application Designer
  • So…what does the application look like? No. 04-12-2008 UKOUG 2008
  • No. 04-12-2008 UKOUG 2008
  • No. 04-12-2008 UKOUG 2008
  • No. 04-12-2008 UKOUG 2008
  • No. 04-12-2008 UKOUG 2008
  • Alternatives No. 04-12-2008 UKOUG 2008 ++ +? ++ ++ UI ++ ++ ++ - Future ++ -/+ + + Knowledge -/+ ++ + + Productivity -/+ ++ -/+ - Costs + ++ + + Performance -/+ + + + Migration .Net APEX JDeveloper Oracle Forms
  • Proof of Concept
      • Re-create some screens on the current DB
      • Reports got a five star rating
      • But what about the forms?
      • Demo
      • Limitations of the default APEX UI:
          • Direct validations
          • Calendar
          • Show description when a code is entered
          • LOV
    No. 04-12-2008 UKOUG 2008
  • Enhancement 1 : Direct Validation
    • 1. Set [HTML Form Element Attribute] to
    • 2. Add a function in the Page HTML Header
    • 2a. Or more ‘state-of-the-art’
    No. 04-12-2008 UKOUG 2008 onchange=“javascript:check_value(this,'Check_Legal_Entity');” <script type=&quot;text/javascript&quot;> function check_value(object, pProcess) { var get = new htmldb_Get(null,$v('pFlowId'),'APPLICATION_PROCESS='+pProcess,$v('pFlowStepId')); get.addParam('x01',$v(object)); gReturn = get.get(); if(gReturn){ alert(gReturn); } } </script> <script type=&quot;text/javascript&quot;> function checkValue(object, pProcess){ var lRequest = new apex.ajax.ondemand( pProcess, function(){ var l_s = p.readyState; if(l_s == 1||l_s == 2||l_s == 3){ } else if(l_s == 4){ gReturn = p.responseText; (gReturn)?myAlert(gReturn, object):null; }else{return false;} } ); lRequest.ajax.addParam('x01',$v(object)); lRequest._get(); } </script>
  • Enhancement 1 : Direct Validation
    • 3. Create an On Demand Application Process ‘Check_Legal_Entity’
    • 2. Add a function in the Page HTML Header
    • Or even better:
    No. 04-12-2008 UKOUG 2008 declare dummy varchar2(1); l_ley_code legal_entity.legal_entity_code%type; begin l_ley_code := upper(wwv_flow.g_x01); if l_ley_code is null then htp.p('Legal Entity is required'); else select '1' into dummy from legal_entity where legal_entity_code = l_ley_code; end if; exception when no_data_found then htp.p('Legal Entity '||l_ley_code||' does not exists'); end begin ley_pck.check_value(upper(wwv_flow.g_x01)); end get.addParam('x01',$v(object)); gReturn = get.get();
  • Enhancement 2 : Calendar
      • Replace the default Calender Pop up window with a jQuery calendar:
        • Display as Text Field
        • Set HTML Form Element Attributes to : class=&quot;datefield“
        • In Page 0 define a ‘document ready’ function to add a datepicker to all fields with that class
    No. 04-12-2008 UKOUG 2008 $(function(){ // Attach a DatePicker icon and function to class=&quot;datefield&quot; $(&quot;.datefield&quot;).datepicker( { dateFormat : 'dd/mm/yy' , closeText : 'X' , clearText : '' , showAnim : 'scale' , showOptions : { origin: ['top', 'left'] } , showOn : 'button' , buttonImage : '#APP_IMAGES#calendar.gif' , buttonImageOnly : true }); });
  • Enhancement 3 : Show description when a code is entered
    • 1. Set [HTML Form Element Attribute] to
    • 2. Add a function in the Page HTML Header
    No. 04-12-2008 UKOUG 2008 get_company_address(this,'LOAD');&quot; <script type=&quot;text/javascript&quot;> function get_company_address(object, pType){ var getter = new htmldb_Get(null,$v('pFlowId').value,'APPLICATION_PROCESS=Get_Company_Address',0); getter.addParam('x01',$v(object)); gReturn = getter.get(); var colArray = gReturn.split(&quot;~sep~&quot;,5); if (colArray[4]==undefined) { alert(gReturn); } else { html_GetElement('P3_'+pType+'_NAME').value = colArray[0]; html_GetElement('P3_'+pType+'_ADRESS').value = colArray[1]; html_GetElement('P3_'+pType+'_COUNTRY_CODE').value = colArray[2]; html_GetElement('P3_'+pType+'_CITY_CODE').value = colArray[3]; html_GetElement('P3_'+pType+'_POSTCODE').value = colArray[4]; } } </script>
  • Enhancement 3 : Show description when a code is entered No. 04-12-2008 UKOUG 2008 4. Create an On Demand Application Process ‘Get_Company_Address’ Or even better: declare l_address varchar2(32000); l_sep varchar2(10) := '~sep~'; l_code address.adress_code%type; Begin l_code := upper(wwv_flow.g_x01); select name||l_sep||adress||l_sep||country_code||l_sep||city_name||l_sep||postcode into l_address from address where adress_code = l_code; htp.p( l_address ); exception when no_data_found then htp.p('Address Code '||upper(v('ADDRESS_CODE'))||' does not exists'); when others then htp.p(sqlerrm); end begin ads_pck.get_address(upper(wwv_flow.g_x01)); end
  • Enhancement 3 : Show description when a code is entered (JSON) No. 04-12-2008 UKOUG 2008 declare l_value varchar2(4000); l_ret_array wwv_flow_global.vc_arr2; begin l_value := upper(wwv_flow.g_x01); -- Address Code if l_value is not null then for a in ( select name||':'||adress||':'||country_code||':'||city_name||':'||postcode retval from address where adress_code = l_value ) loop -- wwv_flow.g_f01(1..5) contains the return fields -- The selected string must be in the same order as the return fields l_ret_array := apex_util.string_to_table(a.retval); for i in 1..wwv_flow.g_f01.count loop apex_util.set_session_state(wwv_flow.g_f01(i), l_ret_array(i) ); end loop; apex_util.json_from_items(apex_util.table_to_string(wwv_flow.g_f01)); end loop; end if; end <script type=&quot;text/javascript&quot;> function getCompanyAddressJSON(object, pType){ if ($v(object)){ var lRequest = new apex.ajax.ondemand( 'getCompanyAddressJSON', function(){ var l_s = p.readyState; if(l_s == 1||l_s == 2||l_s == 3){ } else if(l_s == 4){ gReturn = p.responseText; if(gReturn){ json_SetItems(gReturn); } else{ myAlert('Adresscode '+$v(object)+' does not exist', object); } }else{return false;} } ); lRequest.ajax.AddArray(['P3_UNLOAD_NAME','P3_UNLOAD_ADRESS','P3_UNLOAD_COUNTRY_CODE‘ ,'P3_UNLOAD_CITY_CODE','P3_UNLOAD_POSTCODE']); lRequest.ajax.addParam('x01',$v(object)); lRequest._get(); } } </script>
  • Enhancement 4 : LOV
    • 1. Display as : Text Field
    • 2. Set Post Element Text to :
    • 3. Create a generic ‘LOV-Page’ – based on a LOV Page Template
    • 4. Create a Region (PL/SQL body returning SQL Query) with as source:
    • 5. Create a DB-function get_lov_query, returning a query string from a table
    No. 04-12-2008 UKOUG 2008 &nbsp;<a href=&quot;javascript:ShowLOV('#CURRENT_ITEM_NAME#', 'LOV_CUSTOMERS');&quot;> <img height=&quot;16&quot; width=&quot;16&quot; alt=&quot;Popup Lov&quot; src=&quot;/i/lov_16x16.gif&quot;/></a> return get_lov_query(v('LOV_NAME')); create or replace FUNCTION GET_LOV_QUERY ( p_lov_name IN lov_definitions.lov_name%type ) RETURN lov_definitions.lov_query%type AS l_query lov_definitions.lov_query%type; BEGIN select lov_query into l_query from lov_definitions where lov_name = upper(p_lov_name); RETURN l_query; END GET_LOV_QUERY;
  • Enhancement 4 : LOV
    • 1. Display as : Text Field
    • 2. Set HTML Form Element Attributes to : class=&quot;LOVfield&quot;
    • 3. Define function in document.ready function
    • 4. Create a generic ‘LOV-Page’ – based on a LOV Page Template
    • 5. Create a Region (PL/SQL body returning SQL Query)
    • 6. Create a DB-function get_lov_query, returning a query string from a table
    create or replace FUNCTION GET_LOV_QUERY ( p_lov_item IN lov_items.lov_item%type ) RETURN lov_definitions.lov_query%type AS l_query lov_definitions.lov_query%type; BEGIN select lov_query into l_query from lov_definitions d, lov_items i where i.lov_item = upper( p_lov_item ) and i.lov_name = d.lov_name; RETURN l_query; END GET_LOV_QUERY; select legal_entity_code code, description, company_code company, le_language language, htf.anchor('javascript:passBack('''||legal_entity_code||''')', 'select') choose from legal_entity where legal_entity_code like upper('%'||:P30_LOV_SEARCH||'%') or description like upper('%'||:P30_LOV_SEARCH||'%') or company_code like upper('%'||:P30_LOV_SEARCH||'%') or le_language like upper('%'||:P30_LOV_SEARCH||'%') // Attach a LOV icon and function to class=&quot;LOVfield&quot; $(&quot;.LOVfield&quot;).after('&nbsp;<img class=&quot;LOV-Image&quot; src=&quot;#APP_IMAGES#Search.png&quot; onclick=&quot;javascript:ShowLOV($(this));&quot; />'); No. 04-12-2008 UKOUG 2008 return get_lov_query(v('LOV_ITEM'));
  • Enhancement 4 : LOV
    • 6. Create some Javascript for the interaction
    No. 04-12-2008 UKOUG 2008 javascript:ShowLOV($(this)); return get_lov_query(v('LOV_NAME')); jQuery : Add DIV containing LOV to page
  • No. 04-12-2008 UKOUG 2008 Enhancement 4 : LOV 7. Now you can easily define other draggable multi column LOV’s!
  • The Reaction No. 04-12-2008 UKOUG 2008 Can you do that in APEX too? BTW, we also have a Java written graphical application, tightly connected with the screens. Hey guys, this is really great! .
  • No. 04-12-2008 UKOUG 2008
  • Planboard in APEX : The Demo No. 04-12-2008 UKOUG 2008
  • Planboard in APEX : The Flow No. 04-12-2008 UKOUG 2008 Database APEX Planboard Flow Orders Trucks Planboard View Reports Region 1 2
  • Planboard in APEX : The Reports Region No. 04-12-2008 UKOUG 2008 Normal Report Region Report Region with Containers div_id : cont_<day>_<truck>
  • Planboard in APEX : The Reports Region No. 04-12-2008 UKOUG 2008 Normal Report Region Report Region with Containers div_id : cont_<day>_<truck> Report Region with Containers and Items div_id : item_<day>_<order>
  • Planboard in APEX : The Reports Region No. 04-12-2008 UKOUG 2008 HTML Expression of every (day) column: <div id=&quot;#EQUIPMENT_NO#&quot; class=&quot;dndcontainer&quot; ><div id=&quot;#MON#&quot;>#MON#</div></div> <SCRIPT type=text/javascript> if ('#MON#' != ''){ $('##MON#').addClass('dndobject'); } </SCRIPT> Normal Report Region Report Region with Containers div_id : #equipment_no# Report Region with Containers and Items div_id : #MON#
  • Planboard in APEX : The Flow No. 04-12-2008 UKOUG 2008 Database APEX Planboard Flow Orders Trucks Planboard View Reports Region Application Process Drag & Drop 1 2 3 4
  • Planboard in APEX : The Drag & Drop
    • At first : > 300 LOC JS
    • Application Process handles the updates / inserts in the DB
    • Now : 2 jQuery function calls…..
    No. 04-12-2008 UKOUG 2008
  • Planboard in APEX : The Flow No. 04-12-2008 UKOUG 2008 Database APEX Planboard Flow Orders Trucks Planboard View Reports Region Application Process Drag & Drop 1 2 3 4
  • Planboard in APEX : Context Sensitive Right Mouse Menu No. 04-12-2008 UKOUG 2008
    • jsDOMenu ( http://www.dynamicdrive.com/ )
    • (Re)Define menu on rightclick
    //Add mousedown function to Drag object $(&quot;.dndobject&quot;).rightClick( function(el) { setOrderMenuEntry($(el).attr(&quot;id&quot;)); }) ; lLink = &quot;f?p=&APP_ID.:3:&APP_SESSION.::::P3_ORDER_NO:&quot;+pNo; mainMenu.items.link.actionOnClick=&quot;code:html_PopUp('&quot;+lLink+&quot;','Orders‘,1000,800)&quot;; mainMenu.items.link.setDisplayText( &quot;Go to order &quot;+pNo);
  • Conclusions & Tips
      • Conclusions
      • You really can make an Oracle Forms like application using APEX
      • Even more than that!
      • But you need Javascript / AJAX
      • jQuery rocks!!!
      • Some Free Tips
      • Create a DB schema for the APEX ‘owner’
      • Create views in this schema based on the tables
      • Create instead-of triggers
      • Code as many PL/SQL in the DB
      • Code Javascript in JS-files
      • Use JSON
      • Use FireFox with FireBug (test in IE…and Chrome…)
    No. 04-12-2008 UKOUG 2008
  • Question Time No. 04-12-2008 UKOUG 2008
  • Contact address: [email_address] No. 04-12-2008 UKOUG 2008