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

35
© Logica 2008. All rights reserved Developing a Real-World Logistic Application with Oracle Application Express Roel Hartman Software Architect / NL Lead Technical Architect Oracle

description

 

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

Page 1: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

© Logica 2008. All rights reserved

Developing a Real-World Logistic Application with Oracle Application ExpressRoel Hartman

Software Architect / NL Lead Technical Architect Oracle

Page 2: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

2UKOUG 200804-12-2008

Agenda

Introduction

The Case

Conclusions & Tips

Q&A

Page 3: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

3

Introduction

04-12-2008 UKOUG 2008

www.BloggingAboutOracle.org

roelhartman.blogspot.com

Page 4: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

No. 404-12-2008 UKOUG 2008

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)

Page 5: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

The Client

No. 604-12-2008 UKOUG 2008

• International Bulk Logistic Solution Provider

• Chemical, Food, Gas, Oil, Equipment

• Europe, America, Asia

Page 6: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

The Architecture

No. 704-12-2008 UKOUG 2008

Accounts Payable/Accounts Receivable

administration

Internet

Board computer

software

TMS

Planning

software

Supply Chain Management

Traffic information

Order acceptance and

processing

Communication manager

Onboard computerE

Supply chain management

Mobile internet

Navigation system

Page 7: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

The Technical Environment

No. 904-12-2008 UKOUG 2008

Oracle DBOracle DB

Application Processor

Cache Definition Files

Definition Files

Application Designer

• 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)

• 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)

Page 8: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

So…what does the application look like?

No. 1004-12-2008 UKOUG 2008

Page 9: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

No. 1104-12-2008 UKOUG 2008

Page 10: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

No. 1204-12-2008 UKOUG 2008

Page 11: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

No. 1304-12-2008 UKOUG 2008

Page 12: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

No. 1404-12-2008 UKOUG 2008

Page 13: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

Alternatives

No. 1504-12-2008 UKOUG 2008

+++?++++UI

++++++-Future

++-/+++Knowledge

-/+++++Productivity

-/+++-/+-Costs

+++++Performance

-/++++Migration

.NetAPEXJDeveloperOracle Forms

Page 14: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

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. 1604-12-2008 UKOUG 2008

Page 15: Developing A Real World Logistic Application With Oracle Application - 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. 1704-12-2008 UKOUG 2008

onchange=“javascript:check_value(this,'Check_Legal_Entity');”onchange=“javascript:check_value(this,'Check_Legal_Entity');”

<script type="text/javascript">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="text/javascript">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="text/javascript">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>

<script type="text/javascript">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>

Page 16: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

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. 1804-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

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

begin ley_pck.check_value(upper(wwv_flow.g_x01));end

get.addParam('x01',$v(object));

gReturn = get.get();

Page 17: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

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="datefield“

• In Page 0 define a ‘document ready’ function to add a datepicker to all fields with that class

No. 1904-12-2008 UKOUG 2008

$(function(){ // Attach a DatePicker icon and function to class="datefield" $(".datefield").datepicker( { dateFormat : 'dd/mm/yy' , closeText : 'X' , clearText : '' , showAnim : 'scale' , showOptions : { origin: ['top', 'left'] } , showOn : 'button' , buttonImage : '#APP_IMAGES#calendar.gif' , buttonImageOnly : true });});

$(function(){ // Attach a DatePicker icon and function to class="datefield" $(".datefield").datepicker( { dateFormat : 'dd/mm/yy' , closeText : 'X' , clearText : '' , showAnim : 'scale' , showOptions : { origin: ['top', 'left'] } , showOn : 'button' , buttonImage : '#APP_IMAGES#calendar.gif' , buttonImageOnly : true });});

Page 18: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

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. 2004-12-2008 UKOUG 2008

get_company_address(this,'LOAD');"get_company_address(this,'LOAD');"

<script type="text/javascript"> 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("~sep~",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>

<script type="text/javascript"> 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("~sep~",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>

Page 19: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

Enhancement 3 : Show description when a code is entered

No. 2104-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 );exceptionwhen no_data_found then htp.p('Address Code '||upper(v('ADDRESS_CODE'))||' does not exists');when others then htp.p(sqlerrm);end

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 );exceptionwhen 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

begin ads_pck.get_address(upper(wwv_flow.g_x01));end

Page 20: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

Enhancement 3 : Show description when a code is entered (JSON)

No. 2204-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

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="text/javascript"> 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>

<script type="text/javascript"> 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>

Page 21: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

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;

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') choosefrom 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||'%')

select legal_entity_code code, description, company_code company, le_language language, htf.anchor('javascript:passBack('''||legal_entity_code||''')', 'select') choosefrom 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="LOVfield" $(".LOVfield").after('&nbsp;<img class="LOV-Image" src="#APP_IMAGES#Search.png" onclick="javascript:ShowLOV($(this));" />');

// Attach a LOV icon and function to class="LOVfield" $(".LOVfield").after('&nbsp;<img class="LOV-Image" src="#APP_IMAGES#Search.png" onclick="javascript:ShowLOV($(this));" />');

Enhancement 4 : LOV

1. Display as : Text Field

2. Set HTML Form Element Attributes to : class="LOVfield"

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

No. 2404-12-2008 UKOUG 2008

return get_lov_query(v('LOV_ITEM'));return get_lov_query(v('LOV_ITEM'));

Page 22: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

Enhancement 4 : LOV

6. Create some Javascript for the interaction

No. 2504-12-2008 UKOUG 2008

javascript:ShowLOV($(this));

return get_lov_query(v('LOV_NAME'));

jQuery : Add DIV containing LOV to page

Page 23: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

No. 2604-12-2008 UKOUG 2008

Enhancement 4 : LOV

7. Now you can easily define other draggable multi column LOV’s!

Page 24: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

The Reaction

No. 2704-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!

.

Page 25: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

No. 2804-12-2008 UKOUG 2008

Page 26: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

Planboard in APEX : The Demo

No. 2904-12-2008 UKOUG 2008

Page 27: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

Planboard in APEX : The Flow

No. 3004-12-2008 UKOUG 2008

Database APEX

Planboard Flow

Orders

Trucks

Planboard View Reports Region

1

2

Page 28: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

Normal Report Region

Planboard in APEX : The Reports Region

No. 3304-12-2008 UKOUG 2008

Report Region with Containers

div_id : #equipment_no#

Report Region with Containers and Items

div_id : #MON#

HTML Expression of every (day) column:

<div id="#EQUIPMENT_NO#" class="dndcontainer" ><div id="#MON#">#MON#</div></div><SCRIPT type=text/javascript> if ('#MON#' != ''){ $('##MON#').addClass('dndobject'); }</SCRIPT>

HTML Expression of every (day) column:

<div id="#EQUIPMENT_NO#" class="dndcontainer" ><div id="#MON#">#MON#</div></div><SCRIPT type=text/javascript> if ('#MON#' != ''){ $('##MON#').addClass('dndobject'); }</SCRIPT>

Page 29: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

Planboard in APEX : The Flow

No. 3404-12-2008 UKOUG 2008

Database APEX

Planboard Flow

Orders

Trucks

Planboard View Reports Region

Application Process

Drag &

Drop1

2

3

4

Page 30: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

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. 3504-12-2008 UKOUG 2008

Page 31: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

Planboard in APEX : The Flow

No. 3604-12-2008 UKOUG 2008

Database APEX

Planboard Flow

Orders

Trucks

Planboard View Reports Region

Application Process

Drag &

Drop1

2

3

4

Page 32: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

Planboard in APEX : Context Sensitive Right Mouse Menu

No. 3704-12-2008 UKOUG 2008

• jsDOMenu (http://www.dynamicdrive.com/)

• (Re)Define menu on rightclick

//Add mousedown function to Drag object $(".dndobject").rightClick( function(el) { setOrderMenuEntry($(el).attr("id"));}) ;

//Add mousedown function to Drag object $(".dndobject").rightClick( function(el) { setOrderMenuEntry($(el).attr("id"));}) ;

lLink = "f?p=&APP_ID.:3:&APP_SESSION.::::P3_ORDER_NO:"+pNo;mainMenu.items.link.actionOnClick="code:html_PopUp('"+lLink+"','Orders‘,1000,800)";mainMenu.items.link.setDisplayText( "Go to order "+pNo);

lLink = "f?p=&APP_ID.:3:&APP_SESSION.::::P3_ORDER_NO:"+pNo;mainMenu.items.link.actionOnClick="code:html_PopUp('"+lLink+"','Orders‘,1000,800)";mainMenu.items.link.setDisplayText( "Go to order "+pNo);

Page 33: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

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. 3804-12-2008 UKOUG 2008

Page 34: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

Question Time

No. 3904-12-2008 UKOUG 2008

Page 35: Developing A Real World Logistic Application With Oracle Application - UKOUG 2008

No. 4004-12-2008 UKOUG 2008

Contact address: [email protected]