31
Customization of Oracle Mobile Supply Chain Applications and Oracle Warehouse Management System An Oracle White Paper September 2002

MSCA Customization Oracle White Paper

Embed Size (px)

DESCRIPTION

Customization of Oracle Mobile Supply Chain Applications and Oracle Warehouse Management System-An Oracle White Paper-September 2002

Citation preview

Page 1: MSCA Customization Oracle White Paper

Customization of Oracle Mobile Supply Chain Applications and Oracle Warehouse Management System An Oracle White Paper September 2002

Page 2: MSCA Customization Oracle White Paper

Customization of MSCA/WMS

OVERVIEW Oracle Mobile Supply Chain Applications (MSCA) and Oracle Warehouse Management Systems (WMS) are both comprehensive supply chain solutions for small and large businesses alike. However, given their broad application, not all businesses may want to use these products exactly as shipped. Given that the requirement for customization is possible, the MSCA and WMS products have been architected with a careful use of object hierarchy and an extensible, modular design capable of being customized. In most cases however, customization of Oracle mobile pages shall require basic knowledge of data flow through the customized transactions and an acute knowledge of object-oriented design. Using the tools and tricks provided in this section, either an application developer or a consultant could customize mobile pages for a particular look/feel, or business logic specific to the company’s needs.

Any level of customization, even one using the techniques described within this White Paper that act to reduce ongoing maintenance issues, should be carefully evaluated and cost justified. Just because it looks easy does not mean it is a good idea. Although this document attempts to elucidate a methodology to best customize MSCA and WMS code, it is highly recommended that customers modify and add programmatic code as a last resort. Maintenance, support, liability during patching, duplicated effort, and inconsistency in execution are all elevated through customizations, and consequently may delay a customer’s implementation. Therefore it is always advisable to find non-programatic workarounds if possible.

This document outlines best practices for customization of MSCA and WMS mobile transactions, and delves into the technical details specific to Oracle MSCA and WMS products. The most appropriate readers are implementation consultants attempting to customize the mobile forms specific to a customer’s needs. This document will attempt to elucidate all technical terms and minimize prior knowledge of specific Java coding standards. However, prior basic knowledge of Oracle applications is assumed.

1

Page 3: MSCA Customization Oracle White Paper

The Transaction Structure

Terminology

• Java Bean - A Java Bean is an object of a particular class type, with set variables contained in it and access methods for those variables.

• Mobile Transaction – A full transaction, potentially consisting of one or more mobile pages.

Mobile Application Beans

A mobile application, as defined by MSCA and WMS products, is built using the following Java Beans:

1) A MenuItemBean is needed to attach the mobile application to the Oracle Desktop ERP. It contains no page layout information on its own, but is a necessary conduit to connect the Desktop ERP to mobile transactions. At the leaf node of the FND menu structure lays an FND Form Function that points to the MenuItemBean. The MenuItemBean in itself points to the first page in the application, which is represented by a PageBean.

2) A PageBean represents the unit of display (ie. a single screen on a mobile client). To define a new page, the developer must extend the PageBean, and make a new page bean class. Within this new class, the developer must use the new PageBean's constructor to instantiate FieldBeans (graphical components), and add them to the page.

3) The FieldBean is a super class for all data collection/display graphical components that the developer can use in their pages. When the mobile server loads a new page, it calls the user defined PageBean's constructor, which in turn creates all of the graphical components on that page. Examples of FieldBeans are TextFieldBean, ButtonFieldBean, LOVFieldBean, MultiListFieldBean, ListFieldBean, HeadingFieldBean, SeparatorFieldBean.

Because each of these beans is written in Java, each one can consequently be extended with additional functionality. Customers should have a strong grasp of what a bean is, how the three types of mobile beans relate to each other, and finally how they connect to Oracle Applications Desktop ERP. When constructing a page, it is important to note that ERP forms connects to a MenuItemBean, which in turn links to a PageBean, which in turn contains many FieldBeans, as shown below.

2

Page 4: MSCA Customization Oracle White Paper

F FieldListener

implements MWAFieldListener

P PageBean implements

MWAPageListener

Menu M MenuItemBean

Implements MWAAppListener

Mobile Application Event Logic

An application's runtime logic is specified through the mobile applications event model, a set of interfaces that provide an infrastructure for handling events in an organized and modularized fashion. Based on the existing Java Listener model, a listener can be added to any field, page, or application of your mobile transaction. The following is a list of listeners available:

• FieldEntered – this is called when a particular field is entered. For example, prior to entering a particular field, there may be a need to reinitialize some variables.

• FieldExited – this is called when a particular field is exited. The most common of the listeners, this is used for validation of user input.

• PageEntered – called when the page is entered, this can be used to initialize values on the page.

• PageExited – called when the page is exited, this can perform page level validation logic.

• AppEntered – called when the entire transaction is entered, this can be used to initialize transaction level variables.

• AppExited – called when the entire application is exit, an example use can be to close resources.

• SpecialKeyPressed – this is called when the user presses any special character, such as a Control character. Pressing CTRL-G to generate LPNs or Lots is one example of when this gets called.

Listeners exist to perform validation, hide show fields, reinitialize variables, etc.

Given this transaction structure, please refer to the Appendix (A.1-A.3) for an example of a full transaction. All MSCA and WMS transactions follow nearly the same structure. Therefore, understanding one transaction should lead to faster understanding of all.

3

Page 5: MSCA Customization Oracle White Paper

ADDITIONS IN FUNCTIONALITY OR APPEARANCE The simplest customization is the adding of functionality to a transaction. This may be in the form of adding extra fields, such as an extra button, or adding extra validation when a particular field is exited, or perhaps defaulting the value of a field based on a particular value entered in a previous field. However, this does not entail making modifications to the existing structure and flow the transaction.

Because customization, as the definition of the word, is a very individual process, we shall examine the most frequent cases of customization and deal with each one individually. In the process, you should gain a logical understanding of the object-oriented design practice of inheritance that will guide you in building more specific and custom requirements.

Examples

1) Add application level initialization or destruction

2) Add page level initialization or destruction

3) Adding a field and event handling it

Example 1) In order to add application level logic, you must extend the MenuItemBean and override the existing appEntered and appExited methods. Be certain to include a call to super() when overriding these methods.

M’ MenuItemBeanoverrides appEntered

aand appExited

F FieldListener

implements MWAFieldListener

P PageBean implements

MWAPageListener

Menu M MenuItemBean

Implements MWAAppListener

4

Page 6: MSCA Customization Oracle White Paper

From the above diagram, you can see that M’ extends M and overrides the necessary methods. Now, every time the user navigates to the menu, the new MenuItemBean is launched instead of the original one.

Suppose your company requires a specific global variable be called upon start of a transaction. Here is example code of M’ to accomplish this task.

public class M’ extends M { public void appEntered(MWAEvent e) throws AbortHandlerException,

DefaultOnlyHandlerException, InterruptedHandlerException { super(e); //initialize my company’s global variable here

} }

Now, each time this transaction is entered, the above added logic shall be executed.

Example 2)

Adding page level validation is almost identical to example 1 above, however it is now P that must be extended and the methods pageEntered and pageExited that can be overridden.

Suppose your company requires the user id be displayed on the status bar every time the page is loaded. Here is example code of P’ to accomplish this task.

M’ MenuItemBeanoverrides appEntered

aand appExited

F FieldListener

implements MWAFieldListener

P’ PageBean

overrides pageEntered and

pageExited methods

P PageBean implements

MWAPageListener

Menu M MenuItemBean

Implements MWAAppListener

5

Page 7: MSCA Customization Oracle White Paper

public class P’ extends P {

public void pageEntered(MWAEvent e) throws AbortHandlerException, DefaultOnlyHandlerException, InterruptedHandlerException {

super(e); e.getSession().setStatusMessage(/*Employee User Id*/);

} }

Now, each time this page is entered, the above added logic shall be executed.

Example 3)

Adding and extra field on a page is similar to case 2. The developer is required to first extend P, then in the constructor of P', first call super(), and then instantiate and add the new field. If a new Cancel Button were to be added to P, This can be implemented as follows:

public class P’ extends P {

ButtonFieldBean mCancelBtn; CancelButtonFHandler cancelHandler = new CancelButtonFieldHandler(); public void P'(Session p_session) {

super(p_session); //if the parent constructor takes a session, else use the default constructor mCancelBrn = new ButtonFieldBean(); mCancelBtn.setName("CANCEL"); mCancelBtn.setPrompt("Cancel"); mCancelBtn.addListener(cancelHandler);

// now add the field at the end of the page this.addFieldBean(mCancelBtn);

} }

We must now implement the handler that cancels the transaction:

public class CancelButtonFHandler implements MWAFieldListener { public void fieldEntered(MWAEvent e) throws AbortHandlerException,

DefaultOnlyHandlerException, InterruptedHandlerException { }

public void fieldEntered(MWAEvent e) throws AbortHandlerException, DefaultOnlyHandlerException, InterruptedHandlerException { e.getSession().setNextPageName(MWALib.NEXT_PAGE_NAME_END_OF_TRANSACTION );

} }

Development Choice of development method for customized Java and PL/SQL code is left to the application developer’s discretion. There is no certified or “best” development method for creating custom code. Therefore, it is left to the programmer. Possible methods range from a full-fledged Integrated Development Envirnoment, such as Oracle JDeveloper, to simple editors such as VI or EMACS.

6

Page 8: MSCA Customization Oracle White Paper

Since Oracle JAVA code is not shipped, the Oracle MSCA/WMS team shall provide the Javadocs for all transactions. Therefore, all the APIs, variable names, and private information will be available to the customization developer. To obtain the Javadocs, please download them from the same location as this file.

Deployment All Oracle Java files are located in the $AU_TOP/java/apps.zip file. Custom code can be placed anywhere, as long as its location is in your CLASSPATH. Be certain that you recompile your custom code after every modification, to either apps.zip or the custom code. Additionally, to verify the location of where class files are being picked up by the Mobile Applications Server, it is possible to modify the mwactl.sh file to run java in verbose mode. This will provide a runtime explanation of whether code is being picked from the apps.zip file or the custom code location. For a detailed explanation on the Mobile Applications Server, please refer to the MWA Administration and User guide.

Release Management The Oracle patching process may in the future overwrite any Java or PL/SQL file shipped. Therefore, any strategy for customization must include a method to overcome the headache of re-implementing code change after patches. The strategy mentioned in this document uses object oriented design to never modify original files, and therefore any modification to the original files through patching does not erase custom code. However, it is possible that the execution path of the original files may change, and hence the execution of the custom code may be effected. In this situation it will be necessary to re-evaluate and reprogram the customization. Always remember that customization is a last resort, as there is no fail-safe method of ensuring it need not be rewritten. From a technical standpoint, please remember to recompile all custom code each time a new patch is applied. This will be necessary to ensure proper execution of custom code.

Support Oracle Corporation does not support custom code. Given the innumerable number of customer customizations, it is not possible for Oracle Support Services to debug and fix infinitely many branches of code. Therefore, the person customizing code should be a fairly adroit programmer and capable of development, support, update, and enhancements to the software.

7

Page 9: MSCA Customization Oracle White Paper

Form Function When creating custom classes it is necessary to modify the form functions under the Application Developer responsibility to point to the custom Function instead of the existing one. This can be done by logging into the application developer responsibility and querying the form functions that currently exist.

Query up the existing functions that suit your menu option and copy the data to a new form function. The WebHTML tab must be modified to point to the new Custom function pages. Also make certain that your new form function is pointed to by some menu structure.

BEST PRACTICES CHECKLIST 1) Don’t perform the customization if it can be avoided.

2) Modification of our Java classes and PL/SQL packages directly should be the last resort. Any change made to existing classes and packages may be overwritten every time Oracle releases a new patch. In Java it is always best to extend existing classes and modify functionality. In PL/SQL, it is best to create new packages.

3) Addition of logic and layout is far easier to do versus removal or logic and layout. Therefore, properly evaluate your business needs, see if a workaround exists, and if possible, add logic to obtain the desired result.

Case Studies This section examines specific business needs that are not addressed fully by the Oracle products, and may be required for some businesses. Each case is an example of a real business requirement that has become salient during the Oracle WMS Early Adopter program.

8

Page 10: MSCA Customization Oracle White Paper

Case 1: Removal of the Oracle List of Values (LOV) A large drug manufacturer XYZ recently elicited the need to remove LOVs from mobile transactions and require that every scan be individually validated against the database. This would ensure that if an improper scan occurred, there would no method for the user to select another item from the list of values. Due to the fact that many fields in the mobile transactions are LOVs, at first glance this appeared difficult. However, further examination will show it is far from difficult.

A potential method of achieving this would be to change each of the LOVFieldBeans to TextFieldBeans. However, this method would require that we modify each of the fields and examine in detail the execution logic performed after each field and on the database. This is a feasible method of customization, but not a preferable one. A better route would be to modify the LOVFieldBeans such that they act like TextFieldBeans without changing much code. Let us examine modifying miscellaneous receipts to remove LOVs:

The pertinent miscellaneous receipt transaction files are

oracle/apps/inv/invtxn/server/RcptTrxFunction.java – this file extends from MenuItemBean and contains little logic. It points to the first page of the transaction, the RcptTrxPage, and is pointed to by the FND menu structure on the desktop forms.

oracle/apps/inv/invtxn/server/RcptTrxPage.java – this file is the main transaction page and defines the layout for the page, how classes are initialized, and page level event logic, such as the pageExited and Entered functions.

oracle/apps/inv/invtxn/server/RcptTrxListener.java – this file contains all the field level event logic, such as the fieldEntered and fieldExited methods for every field on the misc receipt page.

It is important not to modify these files directly, as later patches provided by Oracle may overwrite them. Therefore, it is best to extend these classes and modify the extensions. The consultant on this project will create the following files

1) A copy of the INVMTBIS/B.pls file renamed to CUSTOMITEMLOVS/B.pls – this original file contained all the PL/SQL execution for the LOVs. The custom file will copy all this code, with each procedure name changed just a little (so that when it is applied to the database, it doesn’t overwrite the old PL/SQL, or vice versa: when a new patch comes in, it doesn’t get overwritten. Further evaluation may be required to examine if the custom file needs modification when a new patch comes in.) The custom PL/SQL procedures should remove the ‘%’ appended to each of the LOV queries in the file. The ‘%’ is a wildcard, and if we want the LOV to

9

Page 11: MSCA Customization Oracle White Paper

return exactly what is scanned, then removal of this ‘%’ ensures that the LOV will return exact matches only. The ‘%’ needs to be removed in every procedure from the end of each query.

Example Before: select inventory_item_id from mtl_system_items where segment1 like p_item_scanned || ‘%’;

Example After: select inventory_item_id from mtl_system_items where segment1 like p_item_scanned;

Therefore, you can see that the change is minimal, but necessary so that the wildcard is removed.

2) CustomRcptTrxPage extends RcptTrxPage – this file will modify the LOV fields on the page so that they now call the modified PL/SQL instead of the old PL/SQL procedures. Each LOVFieldBean has an object identifier in the original page. The LOVStatement of this object needs to now point to your new PL/SQL that does not have a wildcard. After examination of RcptTrxPage, we discover that the Item Field is identified as ‘mItemFld’. Therefore, we must modify its LOVStatement on the pageEntered of our new custom page. The new code will look something like this:

public class CustomRcptTrxPage extends RcptTrxPage implements

MWAPageListener { CustomRcptTrxPage() {

this.addListener(this); // because this page listens to itself }

public void pageEntered(MWAEvent e) throws AbortHandlerException, DefaultOnlyHandlerException, InterruptedHandlerException {

super.pageEntered(); mItemFld.setLOVStatement(CUSTOM_ITEM_PKG.CUSTOM_RCV_ITEM_PROC); //this line below ensures that the LOV is called mItemFld.setValidateFromLOV(true);

} }

No only does the LOV statement performs exact validation because the wildcard is removed, but it also requires that validate always be performed. *NOTE: This code will only remove LOVs in the misc receipt page. Explanation of how to do it for every transaction is below.

3) CustomRcptTrxFunction extends RcptTrxFunction – this file will extend the base MenuItemBean and point to the CustomRcptTrxPage. Additionally, the FND menu structure should now point to this custom MenuItemBean and this bean must call the super appEntered and appExited methods of the parent.

10

Page 12: MSCA Customization Oracle White Paper

With a simple page fix and PL/SQL fix, this customer was able to remove LOVs in the Item fields of the miscellaneous receipt page. If they had wanted to remove the everywhere, the customer would have had to create an extension for the ItemLOV.java file where all that was done in the pageExited above would be moved into the CustomItemLOV.java file. Then, the new page exited function would look as follows:

public class CustomRcptTrxPage extends RcptTrxPage implements MWAPageListener {

CustomRcptTrxPage() { mItemFld = new CustomItemLOV(“CUSTOM_MISC_RCPT”);

} }

Then, the CustomItemLOV would look like public class CustomItemLOV extends ItemLOV {

CustomItemLOV (String type) { super(); if (type.equals(“CUSTOM_MISC_RCPT”)) {

mItemFld.setLOVStatement(CUSTOM_ITEM_PKG.CUSTOM_RCV_ITEM_PROC); //this line below ensures that the LOV is called mItemFld.setValidateFromLOV(true);

} }

}

Now the removal of LOV logic has been moved to the LOV object itself, rather than just to the page level of the transaction. Subsequent pages must overwrite their current LOV initialization with the new CustomLOVs. This methodology can be extended to other LOV Fields and other mobile transactions. XYZ can now ensure that their drugs are scanned and validated exactly as they are received.

Case 2: Addition of extra fields on Quick Ship Page to collect FOB terms, freight terms, and document shipset.

A large computer manufacturer would like to add extra fields on the quick ship page and therefore allow their mobile shipping employees to scan this extra information at time of using the LPN Quick Ship page provided by Oracle. In order to do this, the custom code developer must extend the existing base class and add additional fields.

For this case, it is best to examine the custom source code and analyze the changes made. From a high level, first the developer will create the three necessary fields that extend from INVFieldBean.

11

Page 13: MSCA Customization Oracle White Paper

INVFieldBean

Implements MWAAppListener

DocumentShipSetLOV Implements

MWAFieldListener

FOBCodeLOV Implements

MWAFieldListener

FreightTermsLOV Implements

MWAFieldListener

oracle/apps/inv/lov/server/DocumentShipSetLOV.java – this class creates the document shipt set LOV. package oracle.apps.inv.lov.server; import java.sql.SQLException; import java.util.Vector; import oracle.apps.fnd.common.VersionInfo; import oracle.apps.inv.utilities.InvResourceTable; import oracle.apps.inv.utilities.server.UtilFns; import oracle.apps.mwa.beans.*; import oracle.apps.mwa.container.MWALib; import oracle.apps.mwa.container.Session; import oracle.apps.mwa.eventmodel.*; // Referenced classes of package oracle.apps.inv.lov.server: // InvLOVFieldBean public class DocumentShipSetLOV extends InvLOVFieldBean implements MWAFieldListener { private String mDocumentShipSetCode; private String mDocumentShipSetMeaning; private String mDocumentShipSetDesc; private static String namePrompt = ""; private static String descPrompt = ""; public DocumentShipSetLOV() { super(); setName("INV.DocumentShipSet"); setlovStatement("XXCS_WMS_UTIL.GET_SHIP_DOCS"); String paramTypes[] = {"C", "S"}; this.setInputParameterTypes(paramTypes); boolean[] displays = {true, true, false}; this.setSubfieldDisplays(displays); this.setRequired(false); this.setHidden(false); this.setValidateFromLOV(true); String[] subprompts = { "A", "A", "A" }; setSubfieldPrompts(subprompts); addListener(this); } public void fieldEntered(MWAEvent e)throws AbortHandlerException, InterruptedHandlerException, DefaultOnlyHandlerException { UtilFns.log("DocumentShipSet: fieldEntered"); setSubPrompts(e.getSession()); }

12

Page 14: MSCA Customization Oracle White Paper

public void fieldExited(MWAEvent e) throws AbortHandlerException, InterruptedHandlerException, DefaultOnlyHandlerException { Session ses = e.getSession(); UtilFns.log("DocumentShipSetLOV: fieldExited" + this.getValue() + "."); if(e.getAction().equals("MWA_SUBMIT")) { try { this.setReturnValues(); } catch(Exception exception) { UtilFns.log("Exception in DocumentShipSetLOV - fieldExited" + exception); throw new AbortHandlerException("Exception in DocumentShipSetLOV - fieldExited" + exception); } } } private void setReturnValues(){ Vector vector = this.getSelectedValues(); if(vector != null) { this.mDocumentShipSetCode = (String)vector.elementAt(2); this.mDocumentShipSetMeaning = (String)vector.elementAt(0); this.mDocumentShipSetDesc = (String)vector.elementAt(1); } } public void clear() { this.setValue(""); this.mDocumentShipSetCode = ""; this.mDocumentShipSetMeaning = ""; this.mDocumentShipSetDesc = ""; } public String getDocumentShipSetCode() { return this.mDocumentShipSetCode; } public String getDocumentShipSetMeaning() { return this.mDocumentShipSetMeaning; } public String getDocumentShipSetDesc() { return this.mDocumentShipSetDesc; } public void setSubPrompts(Session session) { if(namePrompt.equals("")) try { namePrompt = "DocumentShipSetPrompt" ; descPrompt = "DocumentShipSetDescription" ; } catch(Exception sqlexception) { UtilFns.error("Error initialising the lov propmts for DocumentShipSet Lov", sqlexception); } String[] subprompts = { namePrompt, descPrompt, "A" }; setSubfieldPrompts(subprompts); } }

oracle/apps/inv/lov/server/FOBCodeLOV.java – this LOV is for the FOB field and extends from the base INVFieldBean. Notice that all the new fields implement MWAFieldListener. package oracle.apps.inv.lov.server; import java.sql.SQLException; import java.util.Vector; import oracle.apps.fnd.common.VersionInfo; import oracle.apps.inv.utilities.InvResourceTable; import oracle.apps.inv.utilities.server.UtilFns; import oracle.apps.mwa.beans.*; import oracle.apps.mwa.container.MWALib; import oracle.apps.mwa.container.Session; import oracle.apps.mwa.eventmodel.*; // Referenced classes of package oracle.apps.inv.lov.server: // InvLOVFieldBean

13

Page 15: MSCA Customization Oracle White Paper

public class FOBCodeLOV extends InvLOVFieldBean implements MWAFieldListener { private String mFOBCodeCode; private String mFOBCodeMeaning; private String mFOBCodeDesc; private static String namePrompt = ""; private static String descPrompt = ""; public FOBCodeLOV() { super(); setName("INV.FOBCode"); setlovStatement("XXCS_WMS_UTIL.GET_FOB_CODE"); String paramTypes[] = {"C", "N", "S"}; this.setInputParameterTypes(paramTypes); boolean[] displays = {true, true, false}; this.setSubfieldDisplays(displays); this.setRequired(false); this.setHidden(false); this.setValidateFromLOV(true); String[] subprompts = { "A", "A", "A" }; setSubfieldPrompts(subprompts); addListener(this); } public void fieldEntered(MWAEvent e) throws AbortHandlerException, InterruptedHandlerException, DefaultOnlyHandlerException { UtilFns.log("FOBCode: fieldEntered"); setSubPrompts(e.getSession()); } public void fieldExited(MWAEvent e) throws AbortHandlerException, InterruptedHandlerException, DefaultOnlyHandlerException { Session ses = e.getSession(); UtilFns.log("FOBCodeLOV: fieldExited" + this.getValue() + "."); if(e.getAction().equals("MWA_SUBMIT")) { try { this.setReturnValues(); //return; } catch(Exception exception) { UtilFns.log("Exception in FOBCodeLOV - fieldExited" + exception); throw new AbortHandlerException("Exception in FOBCodeLOV - fieldExited" + exception); } } } private void setReturnValues(){ Vector vector = this.getSelectedValues(); if(vector != null){ this.mFOBCodeCode = (String)vector.elementAt(2); this.mFOBCodeMeaning = (String)vector.elementAt(0); this.mFOBCodeDesc = (String)vector.elementAt(1); } } public void clear() { this.setValue(""); this.mFOBCodeCode = ""; this.mFOBCodeMeaning = ""; this.mFOBCodeDesc = ""; } public String getFOBCodeCode(){ return this.mFOBCodeCode; } public String getFOBCodeMeaning(){ return this.mFOBCodeMeaning; } public String getFOBCodeDesc() { return this.mFOBCodeDesc; } public void setSubPrompts(Session session) { if(namePrompt.equals("")) try { namePrompt = "FOBPrompt" ;

14

Page 16: MSCA Customization Oracle White Paper

descPrompt = "FOBDescription" ; } catch(Exception sqlexception) { UtilFns.error("Error initialising the lov propmts for FOBCode Lov", sqlexception); } String[] subprompts = { namePrompt, descPrompt, "A" }; setSubfieldPrompts(subprompts); } }

oracle/apps/inv/lov/server/FreightTermsLOV.java – this LOV collects the freight terms. package oracle.apps.inv.lov.server; import java.sql.SQLException; import java.util.Vector; import oracle.apps.fnd.common.VersionInfo; import oracle.apps.inv.utilities.InvResourceTable; import oracle.apps.inv.utilities.server.UtilFns; import oracle.apps.mwa.beans.*; import oracle.apps.mwa.container.MWALib; import oracle.apps.mwa.container.Session; import oracle.apps.mwa.eventmodel.*; // Referenced classes of package oracle.apps.inv.lov.server: // InvLOVFieldBean public class FreightTermsLOV extends InvLOVFieldBean implements MWAFieldListener { private String mFreightTermsCode; private String mFreightTermsMeaning; private String mFreightTermsDesc; private static String namePrompt = ""; private static String descPrompt = ""; public FreightTermsLOV() { super(); setName("INV.FrieghtTerms"); setlovStatement("XXCS_WMS_UTIL.GET_FREIGHT_TERM_CODE"); String paramTypes[] = {"C", "N", "S"}; this.setInputParameterTypes(paramTypes); boolean[] displays = {true, true, false}; this.setSubfieldDisplays(displays); this.setRequired(false); this.setHidden(false); this.setValidateFromLOV(true); String[] subprompts = { "A", "A", "A" }; setSubfieldPrompts(subprompts); addListener(this); } public void fieldEntered(MWAEvent e) throws AbortHandlerException, InterruptedHandlerException, DefaultOnlyHandlerException { UtilFns.log("FreightTermsCode: fieldEntered"); setSubPrompts(e.getSession()); } public void fieldExited(MWAEvent e) throws AbortHandlerException, InterruptedHandlerException, DefaultOnlyHandlerException { Session ses = e.getSession(); UtilFns.log("FreightTermsLOV: fieldExited" + this.getValue() + "."); if(e.getAction().equals("MWA_SUBMIT")) { try { this.setReturnValues(); //return; } catch(Exception exception) { UtilFns.log("Exception in FreightTermsLOV - fieldExited" + exception); throw new AbortHandlerException("Exception in FreightTermsLOV - fieldExited" + exception); } } } private void setReturnValues() {

15

Page 17: MSCA Customization Oracle White Paper

16

EZShipFunction Implements

MWAAppListener

Menu CustomEZShipFunction

EZShipPage Implements

MWAPageListener

CustomEZShipPage Implements

MWAPageListener

CustomRcvDoneListenerImplements

MWAFieldListener

Vector vector = this.getSelectedValues(); if(vector != null) { this.mFreightTermsCode = (String)vector.elementAt(2); this.mFreightTermsMeaning = (String)vector.elementAt(0); this.mFreightTermsDesc = (String)vector.elementAt(1); } } public void clear() { this.setValue(""); this.mFreightTermsCode = ""; this.mFreightTermsMeaning = ""; this.mFreightTermsDesc = ""; } public String getFreightTermsCode() { return this.mFreightTermsCode; } public String getFreightTermsMeaning() { return this.mFreightTermsMeaning; } public String getFreightTermsDesc() { return this.mFreightTermsDesc; } public void setSubPrompts(Session session) { if(namePrompt.equals("")) try { namePrompt = "FreightNamePrompt" ; descPrompt = "FreightDescription" ; } catch(Exception sqlexception) { UtilFns.error("Error initialising the lov propmts for FreightMethod Lov", sqlexception); } String[] subprompts = { namePrompt, descPrompt, "A" }; setSubfieldPrompts(subprompts); } }

Now that the necessary LOVs have been defined, it is important to modify the custom mobile pages so that the necessary information is collected at the time of shipping. In the Oracle WMS Shipping pages, there exist two means by which a warehouse may ship product. This example will examine both. To start, the EZ Shipping page must be modified so that the custom code will gather the necessary information. From a high level, the architecture looks as follows:

oracle/apps/inv/wshtxn/server/CustomEZShpFunction.java – this page is only the function that points to the first page of the transaction. The

Page 18: MSCA Customization Oracle White Paper

constructor calls the parent’s constructor and sets the first page name to the custom class. package oracle.apps.inv.wshtxn.server; import oracle.apps.mwa.beans.*; import oracle.apps.mwa.container.*; import oracle.apps.mwa.eventmodel.*; import oracle.apps.fnd.common.VersionInfo; import oracle.apps.inv.utilities.server.*; public class CustomEZShpFunction extends EZShpFunction implements MWAAppListener { public CustomEZShpFunction(){ super(); setFirstPageName("oracle.apps.inv.wshtxn.server.CustomEasyShipPage"); } }

oracle/apps/inv/wshtxn/server/CustomEasyShipPage.java – this page adds the four new fields to the page and fixes the inputs of the existing lov’s on the page. The LOVs have been created as shown under the lov/server package. package oracle.apps.inv.wshtxn.server; import oracle.apps.mwa.beans.*; import oracle.apps.mwa.container.*; import oracle.apps.mwa.eventmodel.*; import oracle.apps.fnd.common.VersionInfo; import oracle.apps.inv.lov.server.CarrierLOV; import oracle.apps.inv.lov.server.ShipMethodLOV; import oracle.apps.inv.lov.server.DeliveryLOV; import oracle.apps.inv.lov.server.UomLOV; import oracle.apps.inv.utilities.*; import oracle.apps.inv.utilities.server.*; import oracle.apps.mwa.presentation.telnet.*; import oracle.apps.inv.lov.server.*; import java.sql.*; import java.lang.*; import java.util.Vector; /** * EasyShipPage.java */ public class CustomEasyShipPage extends EasyShipPage implements MWAPageListener { FreightTermsLOV mFreightTermsLOV; FOBCodeLOV mFOBCodeLOV; DocumentShipSetLOV mDocumentShipSetLOV; TextFieldBean NumberOfLPNField, additionalInfoField; public CustomEasyShipPage(Session s) { super(s); } public void pageExited(MWAEvent e) throws AbortHandlerException, InterruptedHandlerException, DefaultOnlyHandlerException { } public void pageEntered(MWAEvent e) throws AbortHandlerException, InterruptedHandlerException, DefaultOnlyHandlerException { super.pageEntered(e); //Be sure to set inputparameters, otherwise LOV will popup everytime field exited. String[] deliveryInputs = {" ", "oracle.apps.inv.wshtxn.server.CustomEasyShipPage.EasyShip.Delivery","ORGID"}; mDeliveryLOV.setInputParameters(deliveryInputs); String[] ShipMethodInputs = {" ", "ORGID", "oracle.apps.inv.wshtxn.server.CustomEasyShipPage.EasyShip.ShipMethod"}; mShipMethodLOV.setInputParameters(ShipMethodInputs);

17

Page 19: MSCA Customization Oracle White Paper

//Add new Field NumberOfLPNField = new TextFieldBean(); NumberOfLPNField.setName("NumberOfLPN"); NumberOfLPNField.setPrompt("# LPN's"); addFieldBean(5,NumberOfLPNField); //Add LOV Field mFreightTermsLOV = new FreightTermsLOV(); mFreightTermsLOV.setName("FreightTerms"); mFreightTermsLOV.setPrompt("Freight Terms"); String[] FreightTermsInputs = {" ", "ORGID", "oracle.apps.inv.wshtxn.server.CustomEasyShipPage.FreightTerms"}; mFreightTermsLOV.setInputParameters(FreightTermsInputs); mFreightTermsLOV.setRequired(false); mFreightTermsLOV.addListener(this); addFieldBean(6, mFreightTermsLOV); //Add new Field additionalInfoField = new TextFieldBean(); additionalInfoField.setName("AdditionalInformation"); additionalInfoField.setPrompt("Add Info"); addFieldBean(7,additionalInfoField); //Add LOV Field mFOBCodeLOV = new FOBCodeLOV(); mFOBCodeLOV.setName("FOB"); mFOBCodeLOV.setPrompt("FOB"); String[] FOBCodeInputs = {" ", "ORGID", "oracle.apps.inv.wshtxn.server.CustomEasyShipPage.FOB"}; mFOBCodeLOV.setInputParameters(FOBCodeInputs); mFOBCodeLOV.setRequired(false); mFOBCodeLOV.addListener(this); addFieldBean(8, mFOBCodeLOV); //Add LOV Field mDocumentShipSetLOV = new DocumentShipSetLOV(); mDocumentShipSetLOV.setName("DocumentShipSet"); mDocumentShipSetLOV.setPrompt("Doc Set"); String[] DocumentShipSetInputs = {" ", "oracle.apps.inv.wshtxn.server.CustomEasyShipPage.DocumentShipSet"}; mDocumentShipSetLOV.setInputParameters(DocumentShipSetInputs); mDocumentShipSetLOV.setRequired(false); mDocumentShipSetLOV.addListener(this); addFieldBean(9, mDocumentShipSetLOV); //get the handle of the Done button field bean Vector v = getFieldBeanList(); FieldBean doneButton = (FieldBean)v.elementAt(10); FieldBean deliveryID = (FieldBean)v.elementAt(0) ; //create custom listener and add it to Deliveryid CustomDeliveryListener cdl = new CustomDeliveryListener(); deliveryID.addListener(cdl) ; //create custom listener and add it to Done button CustomRcvDoneListener crdl = new CustomRcvDoneListener(); doneButton.addListener(crdl); } }

oracle/apps/inv/wshtxn/server/CustomRcvDoneListener.java //Custom Listener Class package oracle.apps.inv.wshtxn.server; import java.sql.*; import java.util.Vector; import java.lang.*; import oracle.apps.mwa.eventmodel.*; import oracle.apps.mwa.container.*; import oracle.apps.mwa.beans.*; import oracle.apps.inv.wshtxn.server.*; import oracle.apps.inv.lov.server.*; public class CustomRcvDoneListener implements MWAFieldListener { public CustomRcvDoneListener() { }

18

Page 20: MSCA Customization Oracle White Paper

public void fieldEntered(MWAEvent e){ } public void fieldExited(MWAEvent e) { Session userSession = e.getSession(); //Get FOBCode from FOB Field FOBCodeLOV fob = (FOBCodeLOV)userSession.getFieldFromCurrentPage("FOB"); String fobValue = fob.getFOBCodeCode(); //Get DocumentShipSetCode from DocumentShipSet Field DocumentShipSetLOV docShipSet = (DocumentShipSetLOV)userSession.getFieldFromCurrentPage("DocumentShipSet"); String docShipSetValue = docShipSet.getDocumentShipSetCode(); //Get FreightTermsCode from FreightTerms Field FreightTermsLOV terms = (FreightTermsLOV)userSession.getFieldFromCurrentPage("FreightTerms"); String termsValue = terms.getFreightTermsCode(); //get handle of Addlinfo. method field and get its value TextFieldBean info = (TextFieldBean)userSession.getFieldFromCurrentPage("AdditionalInformation"); String infoValue = info.getValue(); //get handle of LPN Number int lpnValue=0; TextFieldBean lpn = (TextFieldBean)userSession.getFieldFromCurrentPage("NumberOfLPN"); if( !(lpn.getValue().equals("")) && (lpn.getValue() !=null) ) { lpnValue = Integer.parseInt(lpn.getValue()); } //Get delivery ID to update LOVFieldBean delivery = (LOVFieldBean)userSession.getCurrentPage().getFieldBeanList().elementAt(0); String deliveryValue = delivery.getValue(); userSession.getLogger().log("fr fo doc " + termsValue + fobValue + docShipSetValue, Logger.LOG_SEVERITY_ERROR); try { //use user session's database connection //database connection Connection con = userSession.getConnection(); String procname = "xxcs_wms_util.SET_WSH_NEW_DELIVERIES"; String callableString = "{call " +procname + "(?,?,?,?,?,?,?,?)}"; //Call procedure to update table CallableStatement cs = (CallableStatement) con.prepareCall(callableString); int orgid = Integer.parseInt((String)userSession.getObject("ORGID")); //int orgid = 4; cs.setInt(1, Integer.parseInt(deliveryValue)); cs.setInt(2, orgid); cs.setInt(3, lpnValue); cs.setString(4, termsValue); cs.setString(5, fobValue); cs.setString(6, infoValue); cs.setString(7, docShipSetValue); cs.registerOutParameter(8,Types.VARCHAR); //execute function/procedure cs.executeUpdate(); //Check which button name u are using String name = "Button is "+ (((FieldBean)e.getSource()).getName()); userSession.getLogger().log(name,Logger.LOG_SEVERITY_ERROR); //Check if the Done button is pressed if( ((FieldBean)e.getSource()).getName().equals("EasyShip.Done") && e.getAction().equals("MWA_SUBMIT")){ userSession.getConnection().commit(); userSession.getLogger().log("Committed",Logger.LOG_SEVERITY_ERROR); } //Check if the Next button is pressed from DeliveryLPNPage if( ((FieldBean)e.getSource()).getName().equals("Next") && e.getAction().equals("MWA_SUBMIT")){ userSession.getConnection().commit();

19

Page 21: MSCA Customization Oracle White Paper

userSession.getLogger().log("Committed for Next button in DeliveryLPNPage",Logger.LOG_SEVERITY_ERROR); userSession.getLogger().log("Committed for Next button in DeliveryLPNPage",Logger.LOG_SEVERITY_ERROR); } } //Check if the Done button is pressed from DeliveryLPNPage //Check if the Done button is pressed from DeliveryLPNPage if( ((FieldBean)e.getSource()).getName().equals("Done") && e.getAction().equals("MWA_SUBMIT")){ if( ((FieldBean)e.getSource()).getName().equals("Done") && e.getAction().equals("MWA_SUBMIT")){ userSession.getConnection().commit(); userSession.getConnection().commit(); userSession.getLogger().log("Committed for Done button in DeliveryLPN Page",Logger.LOG_SEVERITY_ERROR); userSession.getLogger().log("Committed for Done button in DeliveryLPN Page",Logger.LOG_SEVERITY_ERROR); } } }catch (SQLException err) { }catch (SQLException err) { userSession.setStatusMessage(String.valueOf(err)); userSession.setStatusMessage(String.valueOf(err)); userSession.getLogger().log(String.valueOf(err),Logger.LOG_SEVERITY_ERROR);

userSession.getLogger().log(String.valueOf(err),Logger.LOG_SEVERITY_ERROR); userSession.getLogger().log("Fail to update table",Logger.LOG_SEVERITY_ERROR); userSession.getLogger().log("Fail to update table",Logger.LOG_SEVERITY_ERROR); } } } } } } Now that the EZ Ship Page has been modified, it is necessary to modify the regular LPN Ship Pages. The architecture is shown as follows:

Now that the EZ Ship Page has been modified, it is necessary to modify the regular LPN Ship Pages. The architecture is shown as follows:

ShipLPNFunction Implements

MWAAppListener

ShipLPNPage Implements

MWAPageListener

DeliveryLPNPage Implements

MWAPageListener CustomShipLPNFunction CustomShipLPNPage

Implements MWAPageListener

CustomDeliveryLPNPage Implements

MWAPageListener Menu

CustomShipLPNFListenerImplements

MWAFieldListener

CustomDeliveryListener Implements

MWAFieldListener

oracle/apps/inv/wshtxn/server/CustomShipLPNFunction.javaoracle/apps/inv/wshtxn/server/CustomShipLPNFunction.java – this is the function that points to the first page of the custom Ship LPN Page.

package oracle.apps.inv.wshtxn.server; import oracle.apps.mwa.beans.*; import oracle.apps.mwa.container.*; import oracle.apps.mwa.eventmodel.*; import oracle.apps.fnd.common.VersionInfo; import oracle.apps.inv.utilities.server.*; public class CustomShipLPNFunction extends ShipLPNFunction implements MWAAppListener { public CustomShipLPNFunction(){ super(); setFirstPageName("oracle.apps.inv.wshtxn.server.CustomShipLPNPage"); } }

oracle/apps/inv/wshtxn/server/CustomShipLPNPage.java – this is the LPN ship page that extends from ShipLPNPage. Notice that this page instantiates a listener for its continue button. //Custom Listener Class package oracle.apps.inv.wshtxn.server; import java.sql.*; import java.util.Vector;

20

Page 22: MSCA Customization Oracle White Paper

import java.lang.*; import oracle.apps.mwa.eventmodel.*; import oracle.apps.mwa.container.*; import oracle.apps.mwa.beans.*; import oracle.apps.inv.wshtxn.server.*; public class CustomShipLPNPage extends ShipLPNPage implements MWAPageListener { ShipLPNFListener fListener; public CustomShipLPNPage(Session s) { super(s); fListener = new ShipLPNFListener(this); } public void pageEntered(MWAEvent e) throws AbortHandlerException, InterruptedHandlerException, DefaultOnlyHandlerException { // call parent pageEntered super.pageEntered(e); String[] inputs = {" ", "TXN.DOCK", "ORGID", "oracle.apps.inv.wshtxn.server.CustomShipLPNPage.ShipLPN.DockDoor"}; mDockFld.setInputParameters(inputs); String[] lpnInputs = {" ", "ORGID", "LOCATORID", "TRIPID","TRIPSTOPID", "oracle.apps.inv.wshtxn.server.ShipLPNPage.ShipLPN.LPN"}; mLPNFld.setInputParameters(lpnInputs); Session session = e.getSession(); ButtonFieldBean continueButton = (ButtonFieldBean)session.getFieldFromCurrentPage("ShipLPN.Ship"); //continueButton.removeListener(fListener); continueButton.removeListener((MWAListener)continueButton.getListeners().firstElement()); session.getLogger().log("Removed Listener",Logger.LOG_SEVERITY_ERROR); //continueButton.setNextPageName("oracle.apps.inv.wshtxn.server.CustomDeliveryLPNPage"); CustomShipLPNFListener csl = new CustomShipLPNFListener(); continueButton.addListener(csl); //session.setStatusMessage("nextpage " + continueButton.getNextPageName()); session.getLogger().log(continueButton.getNextPageName(),Logger.LOG_SEVERITY_ERROR); } public void pageExited(MWAEvent e){} }

oracle/apps/inv/wshtxn/server/CustomShipLPNFListener.java package oracle.apps.inv.wshtxn.server; import java.sql.*; import oracle.apps.mwa.beans.*; import oracle.apps.mwa.container.*; import oracle.apps.mwa.eventmodel.*; import oracle.apps.fnd.common.VersionInfo; import oracle.apps.inv.lov.server.*; import oracle.apps.inv.utilities.server.*; import oracle.apps.inv.utilities.*; import oracle.jdbc.driver.*; import oracle.apps.mwa.presentation.telnet.*; import java.util.Vector; import java.lang.*; import java.sql.*; public class CustomShipLPNFListener implements MWAFieldListener{ public CustomShipLPNFListener(){} ShipLPNPage mParentPage; DockDoorLOV dockDoorFld; ShippingLPNLOV lpnFld; Session session; Connection con; ShipLPNPage curPage; long tripId, locatorId, orgId,dockAppoinmentId,tripStopId,dockDoorId,outermostLpnId;

21

Page 23: MSCA Customization Oracle White Paper

public CustomShipLPNFListener(Session s) { dockDoorFld = null; lpnFld = null; } public CustomShipLPNFListener(ShipLPNPage parent) { this.mParentPage = parent; dockDoorFld = null; lpnFld = null; } public void fieldEntered(MWAEvent e) throws AbortHandlerException, InterruptedHandlerException, DefaultOnlyHandlerException { } public void fieldExited(MWAEvent e) throws AbortHandlerException, InterruptedHandlerException, DefaultOnlyHandlerException { dockDoorFld = null; lpnFld = null; session = e.getSession(); con = session.getConnection(); curPage = (ShipLPNPage)session.getCurrentPage(); dockDoorId = 0; tripId = locatorId = 0; orgId = Long.parseLong((String)session.getObject("ORGID")); if( e.getSource() instanceof ButtonFieldBean && e.getAction().equals("MWA_SUBMIT")) { String buttonName = ((FieldBean) e.getSource()).getName(); session.putObject("SOURCEBTN", buttonName); if( buttonName.equals("ShipLPN.Ship") ) { ButtonFieldBean btnFld = (ButtonFieldBean)e.getSource(); btnFld.setNextPageName(null); checkLPNDeliveries(e); } } } protected void processMissingLpns(CallableStatement cstmt) { UtilFns.log("processMissingLPN"); long deliveryDetailId, locatorId; String outermostLpn, subinventoryCode, locator; deliveryDetailId = locatorId = 0; String deliveryName = ""; outermostLpn = ""; subinventoryCode = ""; locator = ""; try { ResultSet rs = (ResultSet)cstmt.getObject(8); if( rs.next() ) { // there are missing lpn UtilFns.log("Get the missing lpn information, just the first record"); outermostLpn = rs.getString(1); outermostLpnId = rs.getLong(2); deliveryDetailId = rs.getLong(3); subinventoryCode = rs.getString(4); locatorId = rs.getLong(5); locator = rs.getString(6); deliveryName = rs.getString(7); UtilFns.log("outermostLPN is " + outermostLpn); UtilFns.log("outermostLpnId is " + outermostLpnId); UtilFns.log("deliveryDetailId is " + deliveryDetailId); UtilFns.log("subinventoryCode is " + subinventoryCode); UtilFns.log("locatorId is " + locatorId); UtilFns.log("deliveryName is " + deliveryName); UtilFns.log("deliveryName is " + deliveryName); } if( rs.next() ) session.putObject("MISSINGLPN.COUNT",new Long(2)); else session.putObject("MISSINGLPN.COUNT",new Long(1)); rs.close(); session.putObject("MISSINGLPN.LPN", outermostLpn); session.putObject("MISSINGLPN.SUBINVENTORY", subinventoryCode); session.putObject("MISSINGLPN.LOCATOR", locator); session.putObject("MISSINGLPN.DELIVERYNAME",deliveryName); session.putObject("MISSINGLPN.RETURN", "N"); } catch( Exception e) { UtilFns.log("Exception in processMissingLPN: " + e);

22

Page 24: MSCA Customization Oracle White Paper

} } private int promptForMissingLPN(MWAEvent me, long missingCount) { int selectedOption = 1; Session session = me.getSession(); // display the summary first try { String[] promptOption = {MWALib.getAKPrompt(session, InvResourceTable.INV_RT, InvResourceTable.AK_DETAIL_PROMPT), MWALib.getAKPrompt(session, InvResourceTable.INV_RT, InvResourceTable.AK_RETURN_TO_LINES_PROMPT)}; TelnetSession tSes = (TelnetSession)session; Vector tName = new Vector(1,1); tName.addElement("NUMBER_OF_LPN"); Vector tValue = new Vector(1,1); tValue.addElement(""+missingCount); String promptMsg = UtilFns.getMessage(session, "INV", "INV_NUM_MISSING_LPN",tName,tValue); selectedOption = tSes.showPromptPage(MWALib.getAKPrompt(session, InvResourceTable.INV_RT, InvResourceTable.AK_MISSING_LPN_PROMPT), promptMsg, promptOption); } catch (Exception ex) { UtilFns.log("Exception in popup message for missing lpn :"+ex); } return selectedOption; } protected void processMissingItems(CallableStatement cstmt) { UtilFns.log("Process missing items"); long deliveryDetailId, inventoryItemId, requestedQty; deliveryDetailId = inventoryItemId = requestedQty = 0; String deliveryName = ""; Vector deliveryLines = new Vector(); DeliveryLine temp = null; String itemName = ""; String itemDescription = ""; ResultSet rs=null; try { rs = (ResultSet)cstmt.getObject(7); while ( rs.next() ) { //get the information about the missing item deliveryName = rs.getString(1); deliveryDetailId = rs.getLong(2); inventoryItemId = rs.getLong(3); requestedQty = rs.getLong(4); itemName = rs.getString(5); itemDescription = rs.getString(6); temp = new DeliveryLine("",0,deliveryName,deliveryDetailId, inventoryItemId, itemName, itemDescription, requestedQty,"","",0,"",""); deliveryLines.addElement(temp); } DeliveryLineIterator deliveryLinesSeq = new DeliveryLineIterator(deliveryLines); session.putObject("MISSINGITEMSEQ", deliveryLinesSeq); session.putObject("MISSINGITEM.RETURN", "N"); } catch( Exception e) { UtilFns.log("Exception in checkMissingItem: " + e); } finally { try { rs.close(); } catch( Exception e) { UtilFns.log("Exception in checkMissingItem: " + e); } } } protected void processMissingShipset(MWAEvent me, CallableStatement cstmt){ UtilFns.log("Process missing shipset"); Session session = me.getSession(); String shipsetNames = ""; try { shipsetNames = cstmt.getString(9);

23

Page 25: MSCA Customization Oracle White Paper

String[] promptOption = {MWALib.getAKPrompt(session, InvResourceTable.INV_RT, InvResourceTable.AK_CANCEL_PROMPT) }; TelnetSession tSes = (TelnetSession)session; Vector tName = new Vector(1,1); tName.addElement("SHIP_SET_NAME"); Vector tValue = new Vector(1,1); tValue.addElement(shipsetNames); String promptMsg = UtilFns.getMessage(session, "INV", "WMS_WSH_SHIPSET_FORCED",tName,tValue); int selectedOption = tSes.showPromptPage( MWALib.getAKPrompt(session, InvResourceTable.INV_RT, InvResourceTable.AK_SHIPMENT_CONFIRM_PROMPT), promptMsg, promptOption); session.setRefreshScreen(true); session.setNextFieldName("ShipLPN.LPN"); } catch (Exception ex) { UtilFns.log("Exception in popup message for ship set:"+ex); } } protected void checkLPNDeliveries(MWAEvent me) { UtilFns.log("Entering CustomcheckLPNDeliveries"); Session session = me.getSession(); Connection con = session.getConnection(); ButtonFieldBean btnFld = (ButtonFieldBean)me.getSource(); btnFld.setNextPageName(null); String sqlString = "{ call " + " WMS_SHIPPING_TRANSACTION_PUB.CHECK_LPN_DELIVERIES(?,?,?,?,?,?,?,?,?,?,?) }"; CallableStatement cstmt = null; UtilFns.log("Calling check lpn delivery:\n"); outermostLpnId = ((Long)session.getObject("LPNID")).longValue(); tripId = Long.parseLong((String)session.getObject("TRIPID")); dockDoorId = Long.parseLong((String)session.getObject("DOCKDOORID")); orgId = Long.parseLong((String)session.getObject("ORGID")); long deliveryId = ((Long)session.getObject("DELIVERYID")).longValue(); ResultSet rs = null; try { cstmt = con.prepareCall(sqlString); cstmt.setLong(1,tripId); cstmt.setLong(2,orgId); cstmt.setLong(3,dockDoorId); cstmt.setLong(4,outermostLpnId); cstmt.setLong(5,deliveryId); cstmt.registerOutParameter(6, Types.NUMERIC); cstmt.registerOutParameter(7, OracleTypes.CURSOR); cstmt.registerOutParameter(8, OracleTypes.CURSOR); cstmt.registerOutParameter(9, Types.VARCHAR); cstmt.registerOutParameter(10,OracleTypes.CURSOR); cstmt.registerOutParameter(11, Types.NUMERIC); cstmt.execute(); int error_code = cstmt.getInt(6); UtilFns.log("Custom Error code:"+error_code); switch (error_code) { case 0: break; case 1: processMissingItems(cstmt); btnFld.setNextPageName("oracle.apps.inv.wshtxn.server.MissingItemPage"); break; case 2: processMissingLpns(cstmt); btnFld.setNextPageName("oracle.apps.inv.wshtxn.server.MissingLPNPage"); break; case 3: processMissingShipset(me,cstmt); throw new AbortHandlerException("Error:Shipset is not completely shipped"); case 4: session.setStatusMessage(UtilFns.getMessage(session, "INV","INV_FAILED_CREATE_DELI")); UtilFns.log("Error:Failed to create deliveries!"); throw new AbortHandlerException("Error:Failed to create deliveries!");

24

Page 26: MSCA Customization Oracle White Paper

case 5: Vector tName = new Vector(1,1); tName.addElement("DOCK_DOOR_NAME"); Vector tValue = new Vector(1,1); tValue.addElement((String)session.getObject("DOCKDOORNAME")); session.setStatusMessage(UtilFns.getMessage(session, "WMS", "WMS_DOCK_DOOR_EMPTY",tName,tValue)); UtilFns.log("Custom: Nothing to ship"); throw new AbortHandlerException("Custom: Nothing to ship"); default: UtilFns.log("Error: Exception in CustomcheckLPNDeliveries"); } // set if there are one than one deliveries long deliveryCount = cstmt.getLong(11); session.putObject("DELIVERY.COUNT",new Long(deliveryCount)); // get the last delivery info and invoke the delivery lpn page String deliveryName = ""; float grossWeight = 0; String grossWeightUom = ""; String waybill = ""; Delivery delivery = null; String tripName = ""; String shipMethodMeaning = ""; rs = (ResultSet)cstmt.getObject(10); if ( rs.next()) { deliveryName = rs.getString(1); deliveryId = rs.getLong(2); grossWeight = rs.getFloat(3); grossWeightUom = rs.getString(4); waybill = rs.getString(5); tripName = rs.getString(6); shipMethodMeaning = rs.getString(7); UtilFns.log("Custom deliveryName is " + deliveryName + " deliveryId is " + deliveryId); UtilFns.log("Custom grosswieght is " + grossWeight + " grossWeightUOM is " + grossWeightUom); UtilFns.log("Custom waybill is " + waybill + " tripName is " + tripName); UtilFns.log("Custom Ship Method is "+shipMethodMeaning); } else UtilFns.log("Custom Delivery Not FOUND"); delivery = new Delivery(deliveryId, deliveryName, tripName, grossWeight, grossWeightUom, waybill, 0, "",shipMethodMeaning); session.putObject("DELIVERYEO", delivery); btnFld.setNextPageName( "oracle.apps.inv.wshtxn.server.CustomDeliveryLPNPage"); } catch(Exception ex) { UtilFns.log("Exception in CustomcheckLPNDeliveries " + ex); } finally { try { if (rs != null) rs.close(); cstmt.close(); } catch(Exception ex) { UtilFns.log("Exception in CustomcheckLPNDeliveries "+ ex); } } } }

oracle/apps/inv/wshtxn/server/CustomDeliveryLPNPage.java – this page //Creating Custom Page class package oracle.apps.inv.wshtxn.server; import java.sql.*; import java.util.EventObject; import java.util.Vector; import oracle.apps.inv.lov.server.DeliveryLOV; import oracle.apps.inv.lov.server.ItemLOV; import oracle.apps.inv.utilities.InvResourceTable; import oracle.apps.inv.utilities.server.UtilFns;

25

Page 27: MSCA Customization Oracle White Paper

import oracle.apps.mwa.beans.*; import oracle.apps.mwa.container.*; import oracle.apps.mwa.eventmodel.*; import oracle.apps.inv.wshtxn.server.CustomRcvDoneListener; import oracle.apps.inv.wshtxn.server.CustomDeliveryListener; import oracle.apps.inv.wshtxn.server.*; import oracle.apps.inv.lov.server.*; /** * CustomDeliveryLPNPage.java */ //Create custom page class that extends the ShipDeliveryPage public class CustomDeliveryLPNPage extends DeliveryLPNPage implements MWAPageListener { FreightTermsLOV mFreightTermsLOV; FOBCodeLOV mFOBCodeLOV; DocumentShipSetLOV mDocumentShipSetLOV; //Call parent page class constructor public CustomDeliveryLPNPage(Session s){ super(s); } public void pageEntered(MWAEvent e) throws AbortHandlerException, InterruptedHandlerException, DefaultOnlyHandlerException { // call parent pageEntered super.pageEntered(e); //Be sure to set inputparameters, otherwise LOV will popup everytime field exited. String[] deliveryInputs = {" ","TRIPID","ORGID","DOCKDOORID", "oracle.apps.inv.wshtxn.server.CustomDeliveryLPNPage.Delivery"}; mDeliveryFld.setInputParameters(deliveryInputs); String[] ShipMethodInputs = {" ", "ORGID", "oracle.apps.inv.wshtxn.server.CustomDeliveryLPNPage.ShipMethod"}; mShipMethodLOV.setInputParameters(ShipMethodInputs); //Add new Field TextFieldBean NumberOfLPNField = new TextFieldBean(); NumberOfLPNField.setName("NumberOfLPN"); NumberOfLPNField.setPrompt("# LPN's"); addFieldBean(5,NumberOfLPNField); //Add LOV Field mFreightTermsLOV = new FreightTermsLOV(); mFreightTermsLOV.setName("FreightTerms"); mFreightTermsLOV.setPrompt("Freight Terms"); String[] FreightTermsInputs = {" ", "ORGID", "oracle.apps.inv.wshtxn.server.CustomDeliveryLPNPage.FreightTerms"}; mFreightTermsLOV.setInputParameters(FreightTermsInputs); mFreightTermsLOV.setRequired(false); mFreightTermsLOV.addListener(this); addFieldBean(6, mFreightTermsLOV); //Add new Field TextFieldBean additionalInfoField = new TextFieldBean(); additionalInfoField.setName("AdditionalInformation"); additionalInfoField.setPrompt("Add Info"); addFieldBean(7,additionalInfoField); //Add LOV Field mFOBCodeLOV = new FOBCodeLOV(); mFOBCodeLOV.setName("FOB"); mFOBCodeLOV.setPrompt("FOB"); String[] FOBCodeInputs = {" ", "ORGID", "oracle.apps.inv.wshtxn.server.CustomDeliveryLPNPage.FOB"}; mFOBCodeLOV.setInputParameters(FOBCodeInputs); mFOBCodeLOV.setRequired(false); mFOBCodeLOV.addListener(this); addFieldBean(8, mFOBCodeLOV); //Add LOV Field mDocumentShipSetLOV = new DocumentShipSetLOV(); mDocumentShipSetLOV.setName("DocumentShipSet"); mDocumentShipSetLOV.setPrompt("Doc Set"); String[] DocumentShipSetInputs = {" ", "oracle.apps.inv.wshtxn.server.CustomDeliveryLPNPage.DocumentShipSet"}; mDocumentShipSetLOV.setInputParameters(DocumentShipSetInputs); mDocumentShipSetLOV.setRequired(false);

26

Page 28: MSCA Customization Oracle White Paper

mDocumentShipSetLOV.addListener(this); addFieldBean(9, mDocumentShipSetLOV); //Set default values setDefaultValues(e); //get the handle of the Next,Done button field bean and deliveryID Vector v = getFieldBeanList(); FieldBean nextButton = (FieldBean)v.elementAt(10); FieldBean doneButton = (FieldBean)v.elementAt(11); FieldBean deliveryID = (FieldBean)v.elementAt(0) ; //create custom listener and add it to Deliveryid CustomDeliveryListener cdl = new CustomDeliveryListener(); deliveryID.addListener(cdl) ; //create custom listener and add it to Done button CustomRcvDoneListener crdl = new CustomRcvDoneListener(); doneButton.addListener(crdl); nextButton.addListener(crdl); } public void setDefaultValues(MWAEvent e)throws AbortHandlerException, InterruptedHandlerException, DefaultOnlyHandlerException{ Session session = e.getSession(); LOVFieldBean delivery = (LOVFieldBean)session.getCurrentPage().getFieldBeanList().elementAt(0); String deliveryIDValue = delivery.getValue(); String info = "" ; int lpn = 0; String terms = ""; String fob = ""; String docShipSet = ""; try { Connection con = session.getConnection(); String procname = "xxcs_wms_util.GET_WSH_NEW_DELIVERIES"; String callableString = "{call " +procname + "(?,?,?,?,?,?,?,?)}"; //Call procedure to update table CallableStatement cs = (CallableStatement) con.prepareCall(callableString); int orgid = Integer.parseInt((String)session.getObject("ORGID")); cs.setInt(1, Integer.parseInt(deliveryIDValue)); cs.setInt(2, orgid); cs.registerOutParameter (3, Types.INTEGER); cs.registerOutParameter (4, Types.VARCHAR); cs.registerOutParameter (5, Types.VARCHAR); cs.registerOutParameter (6, Types.VARCHAR); cs.registerOutParameter (7, Types.VARCHAR); cs.registerOutParameter (8,Types.VARCHAR); cs.execute(); lpn = cs.getInt(3); terms = cs.getString(4); fob = cs.getString(5); info = cs.getString(6); docShipSet = cs.getString(7); if(info !=null && !(info.equals("")) ){ ((TextFieldBean)session.getFieldFromCurrentPage("AdditionalInformation")).setValue(info); }else{ ((TextFieldBean)session.getFieldFromCurrentPage("AdditionalInformation")).setValue(""); } if(lpn > 0 ){ ((TextFieldBean)session.getFieldFromCurrentPage("NumberOfLPN")).setValue(""+lpn); }else{ ((TextFieldBean)session.getFieldFromCurrentPage("NumberOfLPN")).setValue(""); } if(terms !=null && !(terms.equals("")) ){ ((LOVFieldBean)session.getFieldFromCurrentPage("FreightTerms")).setValue(terms); }else{ ((LOVFieldBean)session.getFieldFromCurrentPage("FreightTerms")).setValue(""); } if(fob !=null && !(fob.equals("")) ){

27

Page 29: MSCA Customization Oracle White Paper

((LOVFieldBean)session.getFieldFromCurrentPage("FOB")).setValue(fob); }else{ ((LOVFieldBean)session.getFieldFromCurrentPage("FOB")).setValue(""); } if(docShipSet !=null && !(docShipSet.equals("")) ){ ((LOVFieldBean)session.getFieldFromCurrentPage("DocumentShipSet")).setValue(docShipSet); }else{ ((LOVFieldBean)session.getFieldFromCurrentPage("DocumentShipSet")).setValue(""); } session.setRefreshScreen(true); session.getLogger().log("Refreshed",Logger.LOG_SEVERITY_ERROR); }catch (SQLException err) { session.getLogger().log("Fail to select from table",Logger.LOG_SEVERITY_ERROR); } } public void pageExited(MWAEvent e){} }

oracle/apps/inv/wshtxn/server/CustomDeliveryListener.java – this is the class that listens the custom delivery lpn page. Notice that on the field exited method all the appropriate data is sent to the database. package oracle.apps.inv.wshtxn.server; import java.sql.*; import java.util.Vector; import oracle.apps.mwa.eventmodel.*; import oracle.apps.mwa.container.*; import oracle.apps.mwa.beans.*; import oracle.apps.inv.wshtxn.server.*; public class CustomDeliveryListener implements MWAFieldListener { public CustomDeliveryListener(){} public void fieldEntered(MWAEvent e){} public void fieldExited(MWAEvent e){ Session session = e.getSession(); LOVFieldBean delivery = (LOVFieldBean)session.getCurrentPage().getFieldBeanList().elementAt(0); String deliveryIDValue = delivery.getValue(); String info = "" ; int lpn = 0; String terms = ""; String fob = ""; String docShipSet = ""; try { Connection con = session.getConnection(); String procname = "xxcs_wms_util.GET_WSH_NEW_DELIVERIES"; String callableString = "{call " +procname + "(?,?,?,?,?,?,?,?)}"; //Call procedure to update table CallableStatement cs = (CallableStatement) con.prepareCall(callableString); int orgid = Integer.parseInt((String)session.getObject("ORGID")); //int orgid = 4; cs.setInt(1, Integer.parseInt(deliveryIDValue)); cs.setInt(2, orgid); cs.registerOutParameter (3, Types.INTEGER); cs.registerOutParameter (4, Types.VARCHAR); cs.registerOutParameter (5, Types.VARCHAR); cs.registerOutParameter (6, Types.VARCHAR); cs.registerOutParameter (7, Types.VARCHAR); cs.registerOutParameter (8,Types.VARCHAR); cs.execute(); lpn = cs.getInt(3); terms = cs.getString(4); fob = cs.getString(5); info = cs.getString(6);

28

Page 30: MSCA Customization Oracle White Paper

docShipSet = cs.getString(7); if(info !=null && !(info.equals("")) ){ ((TextFieldBean)session.getFieldFromCurrentPage("AdditionalInformation")).setValue(info); }else{ ((TextFieldBean)session.getFieldFromCurrentPage("AdditionalInformation")).setValue(""); } if(lpn > 0 ){ ((TextFieldBean)session.getFieldFromCurrentPage("NumberOfLPN")).setValue(""+lpn); }else{ ((TextFieldBean)session.getFieldFromCurrentPage("NumberOfLPN")).setValue(""); } if(terms !=null && !(terms.equals("")) ){ ((LOVFieldBean)session.getFieldFromCurrentPage("FreightTerms")).setValue(terms); }else{ ((LOVFieldBean)session.getFieldFromCurrentPage("FreightTerms")).setValue(""); } if(fob !=null && !(fob.equals("")) ){ ((LOVFieldBean)session.getFieldFromCurrentPage("FOB")).setValue(fob); }else{ ((LOVFieldBean)session.getFieldFromCurrentPage("FOB")).setValue(""); } if(docShipSet !=null && !(docShipSet.equals("")) ){ ((LOVFieldBean)session.getFieldFromCurrentPage("DocumentShipSet")).setValue(docShipSet); }else{ ((LOVFieldBean)session.getFieldFromCurrentPage("DocumentShipSet")).setValue(""); } String id = "orgid is "+ String.valueOf(orgid); session.getLogger().log(id,Logger.LOG_SEVERITY_ERROR); }catch (SQLException err) { session.getLogger().log("Fail to select from table",Logger.LOG_SEVERITY_ERROR); } } }

29

Page 31: MSCA Customization Oracle White Paper

White Paper Title September 2002 Author: Manu Gupta [email protected] Contributing Authors: Copyright © Oracle Corporation 1995 All Rights Reserved Printed in the U.S.A. This document is provided for informational purposes only and the information herein is subject to change without notice. Please report any errors herein to Oracle Corporation. Oracle Corporation does not provide any warranties covering and specifically disclaims any liability in connection with this document. Oracle is a registered trademark and Enabling the Information Ageis a trademarks o

f Oracle Corporation.

Oracle Corporation World Headquarters 500 Oracle Parkway Redwood Shores, CA 94065 U.S.A. Worldwide Inquiries: 415.506.7000 Fax 415.506.7200 Copyright © Oracle Corporation 1995 All Rights Reserved

30