Cloud Inventory® Platform Development Best Practices Guide
About the Cloud Inventory® Platform Development Best Practices Guide
The Mobile Enterprise Platform Development Best Practices Guide describes the recommended standards to use when developing apps in Application Studio. These standards enable you to develop apps and app items with reusable logic and simple maintenance. Without standards, it can be problematic to read, maintain, and debug an application developed by another person.
[Body Empty]
About the development cycle
Mobile Enterprise Platform provides an integrated, standards-based platform for mobile app development that supports the entire application software development life cycle. This enables developers to quickly design, build, deploy, and assess mobile-first applications, and respond to an ever-changing mobile landscape.
The Advanced Inventory application development life cycle is based on DevOps principles with feedback loops within and across phases of the life cycle. The approach encourages communication and collaboration between development and operations teams, supporting continuous process improvement. Applications and their use in the real world are analyzed and assessed by operations and application managers, providing feedback and input that can be used to reassess each application and make improvements as needed.
The diagram below shows how the life cycle elements of development and operations interact in a continuous delivery cycle, which allow you to quickly create and edit apps to respond to evolving requirements.
Development
The following list describes each of the phases in the app development life cycle from a development point of view.
-
Define the specific app requirements you need to execute your predefined business processes.
-
Design your user interaction layer and create functional prototypes. You will often discover additional requirements, or more fully describe existing requirements during this phase.
-
Build the business logic layer of your apps with Application Studio.
-
Integrate with systems of record and cloud-based services.
-
Perform unit testing of the application against sample data within the development environment and debug as necessary.
-
Promote your apps to a user acceptance testing environment.
-
-
Test your apps in a user acceptance testing environment.
-
Confirm you have satisfied your business process requirements.
-
Collect new or revised app requirements, continuing the process.
-
Operations
The following list describes each of the phases in the app development life cycle from an operations point of view.
-
Plan deployment and training for your apps. Formulate and share the strategic vision with the enterprise. These plans strengthen and guide the end user toward application adoption.
-
Deploy live applications into the production environment so users can begin to use them. Solicit, document, and prioritize user feedback for future analysis.
-
Analyze usage and performance metrics with Supply Chain Insights to analyze user behavior and application performance. Evaluate business processes to determine their effectiveness, accuracy, and efficiency.
-
Assess app usage and performance metrics to provide information for application improvements. Review operational alternatives for viability, level of implementation effort, ROI, and technology gaps, and then create or revise your plan, continuing the process. Developers can then use this information to improve the app's usefulness to the end user and the business.
Development standards
Advanced Inventory recommends that you use the following development standards as you create apps, subapps, forms, and wires.
Checking in objects
When you check in an object, you should always enter a comment. There are two basic ways to check in an object. You can check in an object when it is complete or partially complete, as per a specification. The check in comment for these objects should reference the document ID, for example, "DSS V1.2 Application Complete". You can also check in an object that has been modified to fix an issue. The check in comment for bug fixes should describe the fix and include any applicable issue numbers, for example, "issue 132 Fix Customer Name displayed".
After an app is checked in, it must be published again, because the version number is incremented with each check-in. If the app is not published again after a check-in, users will not see it in Advanced Inventory Mobile Client.
Comments
You can add comments to apps to describe complex functionality. Adding a comment does not affect the performance of the app. Advanced Inventory recommends that you use comments often as this speeds up current and future development.About naming conventions for app items
Using definition and development standards for app items helps maintain consistency throughout your organization.
Implementing consistent naming conventions across app items helps developers with future maintenance and usability of the item.
Naming standards can use abbreviations, but whether you use abbreviations or full names, they need to be consistent across your organization. When naming an app, you should keep in mind that depending on a user's Mobile Client settings, they may see the app ID, description, or icon.
App standards
Advanced Inventory recommends that you use the following development standards as you create apps.
App IDs
App IDs should identify the back office system used by the app, and the function the app provides. When naming an app, keep in mind that the app ID, and possibly the description and icon, may, based on their settings, be displayed to Mobile Client users. When naming an app or app item, you should use abbreviations that are consistent across all apps.
App IDs have a maximum length of 30 characters. It is a good practice to use IDs that group apps with similar functionality, such as _INV for Inventory.
Refer to the following examples of naming conventions for app IDs.
JDE_INV_TRANSFER
Back office system: Oracle JD Edwards
Function: Inventory Transfer
SAP_PO_RECEIPT
Back office system: SAP
Function: PO Receipt
EBS_INV_INQUIRY
Back office system: Oracle E-Business Suite
Function: Inventory Inquiry
NS_CYCLE_COUNT
Back office system: NetSuite
Function: Cycle Count
DAX_SHIP_CONFIRM
Back office system: Microsoft Dynamics AX
Function: Ship Confirm
CI_SO_PICKING
Back office system: Cloud Inventory
Function: SO Picking
ASSET_LOCATOR
Back office system: N/A
Function: Asset Locator
Item descriptions
Each item on the flowchart canvas should be given a functional description of the item and its purpose. For example, the description "Get Sales Order Detail Lines for current order" on a download of the JDE sales order detail table (F4211) defines what the table is, and why it is being downloaded.
If you enter an item description, the lower level detail is no longer displayed. If the lower level detail is more useful, you may not need a description.
If you copy an item, the item description is copied as well. These descriptions should be edited to avoid confusion. For example, an app may have multiple variable assignments that clear or set form components. If you copy the clear assignment to set the values, you must modify the description to reflect the new assignment.
Flowcharts
App flowcharts should be organized with a smooth flow from top to bottom, with exceptions branching off. Keep the following considerations in mind as you create your app flowchart.
-
Keep the main app simple.
-
Use a modular code scheme, by creating and utilizing app items such as subapps, includes, and tables.
-
Limit the main application to business processes, and put the details in common elements.
-
Reuse existing, well-tested code to improve development speed and reduce testing time.
-
Data variables that correspond to specific enterprise data elements should use a common numbering scheme.
-
Use the flowchart Connector Entry and Connector Exit elements.
The following example of an app flowchart does not follow these best practices, and does not use any structure. This makes the application hard to follow and complicated to edit. Remember that other developers may need to make updates and edits to the app.
Below is an example of a well-designed flowchart. The app moves smoothly from top to bottom with exceptions branching off to the right, making it easy to read and update.
Exit Application elements
You can use the Exit Application element to define the exit options for an app.
The Exit Application element has a ‘Launch Application On Exit’ option. This option is a great place to call a separate app that clears mobile client tables that were used in the app If this option isn’t used, it is still a good practice to create a subroutine within your app that clears any app-specific data before exiting.
Subroutine standards
Advanced Inventory recommends that you use the following development standards as you create subroutines.
Naming conventions
Each subroutine should have an ID and description that clearly states what the subroutine is trying to accomplish.
Refer to the following examples for more information.
-
GetItemMaster: Download ITEMSMASTER
-
CalcPriceDiscntt: Calculate pricing discount by quantity/customer
-
SetActionCodes: Set action codes for ND3N4210 call
Best practices
Subroutines are self-contained routines that are created within an app, form, or wire that can only be used within that item. You can use subroutines to divide an app into logical components for reuse, and to make the app flowchart readable.
The following subroutines are mandatory in every app.
RevisionHistory
This subroutine contains comments describing the app's functional purpose as well as version history, information stored during Check In, and available documentation versions of issue numbers.
Variables
Defines any app-specific variables, including any that are used for common variables.
InitializeVars
Sets all variables to their initial values, including any Mobile Client tables, as well as clearing out those tables as necessary.
ExitApp
Performs any necessary housekeeping and exits the app. This clears out any Mobile Client tables that are used in lists, so the lists don't initially load with data.
As you manage subroutines, use the following best practices.
-
Code should be written to handle small pieces of functionality to make the flowchart more readable. If necessary, multiple subroutines can be used that are called by other subroutines.
-
Each subroutine should have a name and description that clearly states what the subroutine is trying to accomplish.
-
Consider using subapps for common functions. A subapp is a reusable set of app logic that resides outside an app. Unlike subroutines, which reside within an app, subapps are completely self-contained; their variables are known only to them. For more information, refer to SubApp standards.
Return codes
Subroutines should use return codes when applicable. This includes error return codes as well as business process return codes. Subroutines should always use the following return code: 1 = Error.Additional return codes can be added as needed. The return code should be a single alphanumeric field with a short description about the return code.
SubApp standards
Advanced Inventory recommends that you use the following development standards as you create SubApps.
Naming conventions
SubApp IDs are set based on each SubApp's functional group, as well as the function the SubApp is performing.
SubApp descriptions must contain the SubApp name at the start of the description, and should clearly explain their purpose. For example: GET_LOCATIONS_VALIDATE_ITEM.
SubApps that deal with back office specific functions should also include a prefix indicating the ERP system.
These combine the back office system with the function.
JDE_INV_TRANSFER
Back office system: Oracle JD Edwards
Function: Inventory Transfer
SAP_PO_RECEIPT
Back office system: SAP
Function: PO Receipt
EBS_INV_INQUIRY
Back office system: Oracle E-Business Suite
Function: Inventory Inquiry
NS_CYCLE_COUNT
Back office system: NetSuite
Function: Cycle Count
DAX_SHIP_CONFIRM
Back office system: Microsoft Dynamics AX
Function: Ship Confirm
CI_SO_PICKING
Back office system: Cloud Inventory
Function: SO Picking
ASSET_LOCATOR
Back office system: N/A
Function: Asset Locator
Best Practices
SubApps are self contained routines that are created outside of and then called from any app, form or wire. Mobile Client tables can be used in SubApps to populate data into or out of the SubApp. This can also be thought of as an array going into and out of the SubApp.
SubApps should perform tasks as granularly as possible to enhance their reusability. A simple SubApp can be written to be used in several prompt response apps. Any validation logic can also be used in a SubApp. If any changes are needed, they can be made in the single SubApp instead of in each separate application with an item prompt.
For example:
-
Calculate item price
-
Return order header information for display
-
Display error messages - if using forms or ADC apps, you can use the SubApp to stylize the message screen in one place
-
Enter item numbers
Parameters
You can use parameters in subapps. Parameters should be used to pass data in and out of a SubApp. Output parameters have the ability to return information to the SubApp or item in which it is used.
For information about parameter naming conventions, refer to Parameter standards. Advanced Inventory recommends that you place all input parameters at the beginning of the parameter list, and place all outputs at the end of the list.
For example, if a SubApp contains an input field, add 5 function key description parameters. This adds 5 function keys on the input field that can be used to perform multiple functions depending on how the SubApp is to be used.
You should use a parameter to determine whether the Mobile Client table in the SubApp should be cleared or not. Different situations might require data to be retained instead of deleted.
Return codes
SubApp return codes should be used in the same manner as return codes in subroutines. This includes error return codes as well as business process return codes. SubApps should always use the following return code: 1 = Error.
Additional return codes can be added as needed. The return code should be a single alphanumeric field with a short description about the return code.
You should use return codes rather than returned parameters when an error occurs or no data is found.
Most SubApps should contain a return message parameter to be used in conjunction with return codes. For example, if there is an error return code triggered in the subapp, a return message parameter should also be populated in order for the calling object to display the message.
Form standards
When you create a new form, Advanced Inventory recommends that you apply the following standards.
Naming conventions
Developers use form IDs and descriptions to identify the function or user interface for which they are used. These IDs and descriptions are not visible to Mobile Client users, who see only the app ID and description.
Advanced Inventory recommends that you group forms by name, such as beginning all inventory related forms with "INV_".
For examples of form IDs, refer to the following list.
INV_LOCATIONS
Function/User Interface of Inventory Locations
INV_HEADER
Function/User Interface of Inventory Header
INV_DETAIL
Function/User Interface of Inventory Detail
SHIP_CONFIRM_DETAIL
Function/User Interface of Ship Confirm Detail
ASSET_LOCATOR_DETAIL
Function/User Interface of Asset Locator Detail
Form Elements
Adding a form control automatically creates a control subroutine in the form. A name is automatically assigned based on the control type. The control subroutine is used to add code or functionality to control events. Each control has its own events. You can use subroutines to divide a form into logical components for reuse.
When a form element is added to the canvas, it is assigned a default ID, such as FCTextBox1 or FCLabel1. The ID number increments when an additional form element of the same type is added. To make it easier to identify the function of each form element, you can assign a prefix to the element followed by a descriptive name in camel case. Cloud Inventory® highly recommends that you change the default ID of each form element to a unique ID immediately after adding it to the canvas.
Form element IDs can have a maximum length of 20 characters.
The examples below show form and data controls, their prefixes, and their full control names.
Form controls
Form control | Prefix | Example |
Check Box | chk | chk_ReceiveAll |
Button | btn | btn_Submit |
Panel | pnl | pnl_SalesHeader |
Scroll View | scv | scv_ServiceDetail |
Radio Button | rdo | rdo_ViewDetails |
Text Box | txt | txt_ItemNumber |
Label | lbl | lbl_ServiceOrdNum |
Signature Entry | sig | sig_DeliverySgn |
Tab Container | tab | tab_UserAdministration |
Date Picker | dt | dt_FromDate |
Image | img | img_ServiceImage |
Web View | web | web_RegistrationPage |
Analytics View | any | any_CycleCounts |
Data Controls
Data control | Prefix | Example |
List Box | lst | lst_Locations |
List View | lsv | lsv_ItemLocations |
List View Label | lvl | lvl_Location |
Dropdown List | ddl | ddl_OrderType |
Wire standards
Advanced Inventory recommends that you use the following development standards as you create wires.
Naming conventions
Developers use wire IDs and descriptions to identify the function or user interface for which they are used. These IDs and descriptions are not visible to Mobile Client users, who see only the app ID and description. Wire IDs can have a maximum length of 30 characters.
Advanced Inventory recommends that you group wires by name, such as beginning all inventory related wires with "INV_".
Refer to the following examples of wire IDs.
-
Inventory Lookup = INV_LOOKUP
-
Inventory Inquiry = INV_INQUIRY
-
Inventory Transfer = INV_TRANSFER
-
Ship Confirm = SHIP_CONFIRM
-
Asset Locator = ASSET_LOCATOR
Naming conventions must be maintained throughout the wire in order to avoid conflicts when all wires are merged into the main menu wire.
Subwires
When naming a subwire, use the same naming conventions as the main wire. When the main wire is published, all of the subwires, along with their assets and subroutines are published into one package. This means that subroutine and variable IDs must be unique across all of the subwires. We recommend providing a numeric ID to each subwire, and appending that ID to the end of each subroutine and variable name.
If you fail to adhere to these naming conventions, your app will not publish. For example, if your ship.wire has an ID of 1000, the naming convention for subroutines and variables should match the following.
-
Subroutine: GET_ORDERS_1000 UPLOAD_STATUS_1000
-
Variables: V_sOrderType_1000 V_nOrderNumber_1000
Wire subroutines
Wire subroutines must have unique IDs specific to your wire and between your wire and its subwires. Most wire subroutines required by your wire are automatically created, but in the event that you need to create a new Wire subroutine, refer to the following example.
Example: In a wire named CI_Asset_Mgmt_1050, for a subroutine that searches for an item, the ID is SEARCH_ITEM_1050.
If the character limit prevents you from adding the full wire number, shorten the name of the subroutine in a meaningful way, such as SRCH_ITM_1050.
Wire variables
Wire variables must have unique names specific to your wire document and between your wire and its subwires. Most wire variables required by your wire are automatically created. In the event that you need to create a new variable, use the format
V_{s/n}VariableName_DocID
, where s/n is used to denote string or numeric for the variable. Example: In a wire named CL_CL_Asset_Mgmt_1050, for a string variable that is used for generic searches, the ID is V_sSearchString_1050.
If the character limit prevents you from adding the full wire number, shorten the name of the variable in a meaningful way, such as V_sSrchStrng_1050.
Best practices
Wires use <import> and <include> tags to build complex applications using multiple resources. The wire language enables you to develop engaging and intuitive apps. However, due to the single document nature of wire, using it to develop complex apps can be difficult. It's not uncommon for a wire file of a moderately complex app to be thousands of lines long. This can cause problems during and after development, as troubleshooting becomes more prohibitive with such a large amount of data.
Additionally, because a wire is a single document, Application Studio's check in and check out functionality only allows one user to make edits at a time. This makes utilizing multiple resources for one Wire app difficult, leading to longer than necessary timelines and inefficient workflows.
Wire provides methods to resolve both of these issues: the include tag and the import tagThe <include> tag loads a separate wire, or subwire, into another wire, or main wire. This can be done on demand during the app session using the <load> tag. When the subwire is loaded, it is loaded into its own context separate from the main wire, effectively separating all wire variables, objects, and subroutines from the main wire or other subwires.
The <import> tag inserts wire code from a separate wire into another wire. This allows a standard set of wires, or "snippets", to be developed and implemented across a number of wires. Doing so ensures that styles, object behavior, and functionality remain consistent. Due to its centralized nature, <import> also allows mass edits, such as a background color change, or a text label change, to be implemented to a single import file. The wire code from an <import> is inserted at runtime and cannot be modified afterwards.
For an example of a wire developed using these best practices, refer to Wire example.
Subwires
Because variables and subroutines are unique to each subwire, if you need to pass information from one subwire to another, you must use a wire preference or a subroutine to pass data.
A wire preference behaves like a variable and resides at the main wire level, but is persistent across sessions and still assignable by subwires. For example, if you need to pass an order number between the ship.wire file and the receive.wire file, you should use the following wire preferences.
-
In the ship.wire file, assign the preference:
<assign property="preferences:orderNumber" value="12345" />
-
In the receive.wire file, read the preference:
<alert message="orderNumber is [preferences:orderNumber]" />
Note:The naming conventions for Mobile Enterprise Platform subroutines and variables are not required for wire preferences. Wire elements are not packaged into the main app on publish in the same way that the Mobile Enterprise Platform objects are packaged.
If you want to pass a large amount of data between the ship.wire file and the receive.wire file, you should use a subroutine instead of a wire preference. You can accomplish this by using a subroutine to populate a Mobile Client table in the ship.wire file. You can then use a subroutine to read the table in the receive.wire file.
Wire example
For information about creating a wire, refer to the following example.
Example
You need to build an app with a main menu, and with three options of Ship Order, Receive Order, and Create Order. Each of these three options must be worked on by three different resources, and then loaded independently of each other. To achieve this, you can build each screen as a subwire that is loaded into an <include> tag within the main menu app. The code across all three screens must be as consistent as possible, from both a look and feel perspective, and a code perspective. Design edits may be needed, and should be applied in one central file and disseminated across all three wire files. To achieve this, each subwire uses a set of <import> tags.
Utilizing a combination of the <
include
> tag and <import
> tags enables you to create complex, multi-screen apps, developed with a number of different resources, while still maintaining a standard, centrally located code base that can be easily modified and debugged. This can all be done while maintaining a consistent look and feel throughout the app. By combining these methods along with other advanced wire concepts and Mobile Enterprise Platform integrations, you should be able to create powerful apps that meet both the client's business requirements and provide experiences that are compelling and intuitive to the end user.The following code example shows the main wire. It is a simple menu "container" with a menu bar at the top of the screen that has three options: SHIP ORDER, RECEIVE ORDER, and CREATE ORDER. Below the menu is the panel that will contain the <
include
> tag. <wire> <main> <panel name="top" width="100%" height="100%" background="#ffffff" > <panel name="menu" width="100%" height="5%" background="#cccccc" > <text name="ship" width="300" height="100%" font="Arial" size="18" color="#000000" text="SHIP ORDER" /> <text name="receive" width="300" height="100%" rightof="ship" font="Arial" size="18" color="#000000" text="RECEIVE ORDER" /> <text name="create" width="300" height="100%" rightof="receive" font="Arial" size="18" color="#000000" text="CREATE ORDER" /> </panel> <panel name="content" width="100%" height="95%" valign="bottom" > <include name="include" alias="INCLUDE" width="100%" height="100%" background="#66ccff"/> </panel> <panel name="exit" width="50" height="50" align="right" valign="bottom" background="#ff0000" onclickup="wire-exit" > <text name="lbl" width="100%" height="100%" font="Helvetica" color="#000000" size="14" text="Exit" alignment="center" /> </panel> </panel> </main> <actions> <action name="wire-exit" > <event type="exit" /> </action> </actions> </wire>You can add
onclickup
events to each of the text objects in the menu to call the "load-wire" action. Then you can use an object variable to pass down the name of the wire, using one generic action. Refer to the following code for an example.<panel name="menu" width="100%" height="5%" background="#cccccc" > <text name="ship" width="300" height="100%" font="Arial" size="18" color="#000000" text="SHIP ORDER" onclickup="load-wire" _wire+"ship" /> <text name="receive" width="300" height="100%" rightof="ship" font="Arial" size="18" color="#000000" text="RECEIVE ORDER" onclickup="load-wire" _wire="receive" /> <text name="create" width="300" height="100%" rightof="receive" font="Arial" size="18" color="#000000" text="CREATE ORDER" onclickup="load-wire" _wire="create" /> </panel>To enable the
onclickup
events to call the "load-wire" action, you must add the action to the wire. The "load-wire" action uses the <load
> tag to load a wire into the <include
>. You should also use an <assign
> tag to convert the object variable _wire
to a global variable [var.loadedWire]
in case it is needed for later actions within the workflow. To make sure that the variable assignment happens before the <include> is loaded, wrap the <assign
> tag and the <load
> tag in a <sync
> tag. Refer to the following code for an example.<action name-"load-wire" > <sync> <assign property="var:loadedWire" value-"_wire" /> <load file+"[var:loadedWire].wire" wirename="[var:loadedWire." target="INCLUDE" /> < /sync> </action>The full main wire should now match the following code.
<wire statusbarhide="yes" > <main> <panel name="top" alias="TOP" width="100%" height="100%" background="#ffffff"/> <panel name="menu" width="100%" height="5%" background="#cccccc" /> <text name="ship" width="300" height="100%" font="Arial" size="18" color="#000000" text="SHIP ORDER" onclickup="load-wire" _wire="ship" /> < text name="receive" width="300" height="100%" rightof="ship" font="Arial" size="18" color="#000000" text="RECEIVE ORDER" onclickup="load-wire" _wire="receive" /> <text name="create" width="300" height="100%" rightof="receive" font="Arial" size="18" color="#000000" text="CREATE ORDER" onclickup="load-wire" _wire="create" /> <panel /> <panel name="content" width="100%" height="95%" valign="bottom" > <include name="include" alias="INCLUDE" width="100%" height="100%" background="#66ccff " /> <panel /> <panel name="exit" width="50" height="50" align="right" valign="bottom" background="#ff0000" onclickup="wire-exit" > <text name="lbl" width="100%" height="100%" font="Helvetica" color="#000000" size="14" text="Exit" alignment="center" /> <panel /> <panel /> <main /> <actions /> < action name+"load-wire"/> < sync> <assign property="var:loadedWire" value="_wire"/> <load file="[var:loadedWire].wire" wirename="[var:loadedWire]" target="INCLUDE"> </sync> <action> <action name="wire-exit" /> <event type="exit" " /> < /action> </action> </wire>If you launch the app and select a menu option, nothing is loaded. Subwires still need to be created and added to the resources for the main wire.
Subwires
Create a simple subwire for each menu option. Each subwire should have a colored background and a text object labeling it.
After you create the subwires, create a new wire for each subwire. Each wire should correspond to one of the subwires and use the same name: ship, receive, and create. Refer to the following code for examples.
ship
receive <wire> <main> <panel name="top" alias="TOP" width="100%" height="100%" background="#00ff00"> <text name="label" width="100%" height="100%" font="Arial" size="24" color="#ffffff" alignment="center" text="SHIPPING WIRE" /> </panel> < /main> </wire
<wire> <main> <panel name="top" alias="TOP" width="100%" height="100%" background="#00ff00"> <text name="label" width="100%" height="100%" font="Arial" size="24" color="#ffffff" alignment="center" text="RECEIVING WIRE" /> </panel> < /main> </wire>
create
All resource wires are included after the main app is published. At this point, each subwire can be worked on independently, allowing the most efficient use of development resources while avoiding conflict. <wire> <main> <panel name="top" alias="TOP" width="100%" height="100%" background="#0000ff"> <text name="label" width="100%" height="100%" font="Arial" size="24" color="#ffffff" alignment="center" text="CREATE ORDER WIRE" /> </panel> < /main> </wire>After you create the wires above, you must associate them with the main wire. For instructions, refer to Add a resource wire file to a wire.
For more information on working in subwires, refer to Wire standards.
After your subwires are functional, the recommended naming conventions are applied and a method to pass data back and forth is complete, you can focus on standardizing the code. Using standardized code for each subwire ensures that each element looks and functions the same for the end user. This is important when multiple resources work on the same wire app.
Standardized code also helps with future development and troubleshooting. It also allows you to apply changes to each subwire at once. You can accomplish this using wire snippets and the <
import
> tag. Imports
Before you create a snippet, you must create a standalone wire file to contain it. Imported code is inserted at runtime, so each top-level block in the importing wire requires its own <import> tag. This example uses an import in the <
styles
> block, <classes
> block, and <actions
> block.Note that <
import
> tags insert the snippet of code into the importing wire, eliminating the need for a root level <wire
> tag or the block <styles
> tag. Because you are not using root level tags, you will not be able to validate the wire code within an import fileStyles
You can use an import in the <
styles
> block to control the look and feel of text objects across all screens. Additionally, you can create a style that applies left and right padding on objects to standardize the look and feel and code for each screen. Refer to the following code for an example.<style name="label" font="Arial" size="16" color="#000000"> <style name="padding" padding-left="10" padding-right="10" padding-top="15" padding-bottom="15" />
Classes
You can use an import in the <
classes
> block to create classes for objects to be laid out in your subwire. It should contain a class for a textfield with a label, and a class for a button. Refer to the following code for an example.<class name="textfield" > <panel name="[param:name]" width="200" fitheight="yes" xpos="[eval: ([param:col] - 1) * 250]"> <text name="lbl" width="100%" height="fit" style="label" text="[param:textLabel]" /> <panel name="input" width="200" height="40" bottomof="lbl" background="#ffffff" borderwidth="1" bordercolor="000000" /> <textfield name="field" alias="[param:fieldAlias]" width="100%" height="100%" style="label" /> < /panel> < /panel> < /class> < class name="button" /> <panel name="[param:name]" width="100" height="40" align="right" valign="bottom" background="#000000" onclickup="show-alert" _associatedField="[param:associatedField]" _nextAction="[param:nextAction]" /> < text name="lbl" width="100%" height="100%" font="Arial" color="#ffffff" size="14" text="[param:buttonLabel]" alignment="center"/> < /panel> < /class>The code above calls the styles from the styles.wire import file to determine the text for the label within the textfield class. The xpos for the textfield is determined by a calculation using the value of the "col" param. This ensures that each item will be placed on the same horizontal plane with an equal 50px padding between each.
It also contains the "show-alert" action, which will be fired when a user clicks the button. It uses the value of the _associatedField object variable to pass down the alias of the text field associated with the action. This allows for having multiple text fields on a screen, each passing down their own information to a generic action that will be defined in the actions.wire import.
Actions
You can use an import in the <
actions
> block to convert the object variable to a global variable, and display an alert message showing the contents of the associated textfield. You can also trigger an action to play after the alert displays. To allow the triggered action to be unique for each screen, you can make the action dependent on an object variable passed down from the class. This allows us to provide a generic set of actions for all screens, but still allow the developer of each screen to add additional actions that might be necessary for their screen. For an example, refer to the code below.
<action name="show-alert" > <sync> <assign property="var:activeField" value="_associatedField" /> <alert message="Content of the active field is [object:[var:activeField].text]" /> <play action="_nextAction" /> </sync> </action>
Subwire
After you create import files for your styles, classes and actions, you can import them into a subwire. Using the receiving.wire subwire, add the wire files to be imported into the resources for the wire. Then add an import tag into the necessary blocks within the subwire and call the wire. For an example, refer to the code below.
<wire> <styles> <import file="styles.wire" /> </styles> <classes> <import file="classes.wire" /> </classes> <main> <panel name="top" alias="TOP" width="100%" height="100%" background="#00ff00" /> <text name="label" width="100%" height="100%" font="Arial" size="24" color="#ffffff" alignment="center" text="RECEIVING WIRE" /> </panel> </main> <actions> <import file="actions.wire" /> </actions> </wire>
When this subwire is loaded into the main wire, the imported wires are inserted into their respective blocks.
After you import the resource wire files into your subwire, you can add the classes and actions that are specific to this wire. For this example, create one row with three columns, and add a textfield to each column. These fields should be labeled Order Number, a textfield for Order Type, and Order Status.
Add a button which, when pressed, displays an alert with the order number and fires an additional action that is unique to this wire.
Add the unique action to the <
actions
> block, below the import tag. This sets the alpha to a text tag of 1 and assigns the text value with the value of the Order Number textfield. For an example, refer to the code below. <wire> <styles> <import file="styles.wire" /> </styles> <classes> <import file="classes.wire" /> </classes> <main> <panel name="top" alias="TOP" width="100%" height="100%" background="#ffffff" /> <panel name="row1" width="100%" height="135" background="#cccccc" style="padding" ypos="15%" /> <object class="textfield" name="orderNo" textLabel="Order Number" fieldAlias="ORDER-NO" col="1" /> <object class="textfield" name="orderType" textLabel="Order Type" fieldAlias="ORDER-TYPE" col="2" /> <object class="textfield" name="orderStatus" textLabel="Order Status" fieldAlias="ORDER-STATUS" col="3" /> <object class="button" name="submit" associatedField="ORDER-NO" buttonLabel="SUBMIT" nextAction="show-complete" /> <panel /> <panel name="message" width="100%" height="50" valign="center" alpha="0"l> <text name="lbl" width="100%" height="100%" style="label" text="PLACEHOLDER" alignment="center" > </panel> </panel> </main> <actions> <import file="actions.wire" /> <action name="show-complete" > <sync> <assign property="object:TOP/message/lbl.text" value="SUCCESS! ORDER [object:[var:activeField].text] RECEIVED." /> <alpha value="1" time=".25" target="TOP/message" /> <sync> </action> </actions> </wire>
Test the completed app and wire
Run the app and select RECEIVE ORDER from the main menu. These three fields should display.
-
Order Number
-
Order Type
-
Order Status
Next, enter data in the Order Number field and press Enter. An alert message should display. When you dismiss the alert, the text label should display with a success message.
Configuration element standards
Advanced Inventory recommends that you use the following development standards as you create configuration elements.
Naming conventions
Configuration element IDs should identify the associated functionality and system.
For example, if you are creating a configuration element for the JDE processing option version for inventory transfers, the name should indicate the JDE interface ND3N4113 and the version, such as "ND3N4113PO".
The configuration element description should contain both the ID and a description of the element. This is because when viewing the application configuration, the description displays by default. The ID does not display until a user selects the information icon. Entering the ID into the description field makes it easier for users to find specific configuration elements.
For example, the configuration element in the example above should have the description "ND3N4113PO - P4113 Processing Option Version".
Best practices
You should assign each configuration element to an appropriate category. If the configuration element is tied to an ERP system, the ERP system should be the category.
For examples of configuration element categories, refer to the following list.
-
JDE
-
NS
-
EBE
-
SAP
-
PARCEL_CARRIER
-
IFS
-
MOBILEApps
Connection string standards
Advanced Inventory recommends that you use the following development standards as you create connection strings.
Naming conventions
Connection string IDs are required, and may not be edited after the connection string is created and saved. When creating a connection string ID, use the format
{database type}_{type of data}
. For examples of connection string IDs, refer to the following table.
Development promotion level | Production promotion level |
MEPDB_SYSDATA | MEPDB_SYSDATA |
JDEDB_BUSDATA | JDEDB_BUSDATA |
Best practices
In the examples above, the connection string IDs are the same in each promotion level for application promotion purposes. If apps using a connection string will be promoted to another environment, it is important that a connection string is created in both environments with the same ID. The string itself is very similar, but the initial catalog, user ID, password, and schema will likely be very different.
Examples
The following common connection string names are often used on Mobile Enterprise Platform server installations. Advanced Inventory highly recommends that you use names that are similar to the examples below.
Purpose | ID | Example environment | Description |
Custom Application Tables | CUSTDB_CUSTDATA | DV910 | Custom Table Data - DV910 |
Custom Application Tables | CUSTDB_CUSTDATA | PY910 | Custom Table Data - PY910 |
MEP System Tables | MEPDB_SYSDATA | DV910 | MEP System Tables - DV910 |
MEP System Tables | MEPDB_SYSDATA | PY910 | MEP System Tables - PY910 |
MEP Middle Tier Tables | MEPDB_MTDATA | DV910 | MEP Middle Tier Tables - DV910 |
MEP Middle Tier Tables | MEPDB_MTDATA | PY910 | MEP Middle Tier Tables - PY910 |
MEP System Tables | MEPDB_SYSDATA | *SYSTEM | MEP System Tables - System |
Purpose | ID | Example environment | Description |
JDE Business Data Tables | JDEDB_BUSDATA | DV910 | JDE Business Data - DV910 |
JDE Business Data Tables | JDEDB_BUSDATA | PY910 | JDE Business Data - PY910 |
JDE Control Tables Data Tables | JDEDB_CTLDATA | DV910 | JDE Control Tables Data - DV910 |
JDE Control Tables Data Tables | JDEDB_CTLDATA | PY910 | JDE Control Tables Data - PY910 |
Function Call standards
Advanced Inventory recommends that you use the following development standards as you create function calls.
Naming conventions
Function Call IDs should reflect the source object in the back office system, with an additional brief description about the use of the function. When specifying a function call ID, keep the following considerations in mind.
-
Function call IDs must have a prefix of C_.
-
The maximum length of a function call ID is 20 characters.
The function call description should provide a technical link to the back office followed by more detailed information about the function usage.
Examples
A JDE application calls dcLINKShipmentConfirmation (ND3N4205) to ship and complete individual lines, and to complete the entire order depending on user selection. These function calls are named and described as follows.
C_ND3N42055ShipConfLn
NDEN4205 Ship Confirm Individual Line
C_ND3N42055ShipConfOr
NDEN4205 Ship Confirm Order
Mobile Client table standards
Advanced Inventory recommends that you use the following development standards as you create Mobile Client tables.
Naming conventions
You should name Mobile Client tables after the data they contain. Mobile Client table IDs can have a maximum length of 30 characters, and always have a prefix of "T_".
For example, a JDE ADC implementation of multiple inventory inquiries uses a SubApp to retrieve item details, including quantity, lot, and expiry. These details are stored in a MC table called "T_InquiryDetails".
All field names within a Mobile Client table must be in uppercase and describe the data they hold.
Include standards
Advanced Inventory recommends that you use the following development standards as you create includes.
Naming conventions
Each include ID should reflect the purpose of the include, including the type of ERP system. Include IDs have a maximum length of 30 characters.
Refer to the following examples of include IDs.
JDE_INV
Inventory variables
Back office system: Oracle JD Edwards
SAP_SALES
Sales variables
Back office system: SAP
EBS_WO
Work order variables
Back office system: Oracle E-Business Suite
NS_SALES
Sales variables
Back office system: NetSuite
DAX_INV
Inventory variables
Back office system: Microsoft Dynamics AX
CI_SALES
Sales variables
Back office system: Cloud Inventory
ASSET_VARIABLES
Asset Locator variables
Back office system: N/A
Some includes are commonly used, such as an include for default variables or start up variables.
The following include names and descriptions are commonly used in Mobile Enterprise Platform apps.
JDE_DFLTV
Include for default variables that may be common to multiple applications.
Example: Version
JDE_SU
Include for startup variables that may be specific to multiple applications.
Example: Branch Plant
Copyright
Include for a collection of comments that represent a copyright.
DSI_PRINT
Include specific for variables used in Cloud Inventory® printing.
Best practices
You can use an include to group a collection of variables and associated comments together. You can reference an include in an app with the include element. The include is then copied into the app during publishing.
Includes should only contain variables and comments associated with one functional area. As code is written for new functional areas, create new includes to prevent performance issues. Large includes can create delays when debugging or selecting a variable in the formula builder.
Download standards
Advanced Inventory recommends that you use the following development standards as you add a Download source element to an app.
Naming conventions
Download IDs should identify the table the download is referencing. When specifying a download ID, keep the following considerations in mind.
-
Additional information should be included if the table is being downloaded multiple times.
-
Download IDs are always prefixed with a D_.
-
Download IDs have a maximum length of 20 characters.
The description of the download should contain more detailed information about its usage.
Examples
A JDE ADC implementation of Work Order Completions has two downloads of the work order part list (F3111). One download gets all entries by work order number. The other download checks for multiple entries by item and lot number.
The following downloads refer to the examples in the table shown below.
-
D_F3111_AllParts - All parts in the parts list.
-
D_F3111_ItemLotChk - Check for item and lot in parts list.
Table | Purpose | Download ID |
F4101 | Get Item Master | D_F4104GetItem |
F41021 | Get Item Locations | D_F41021GetLocations |
F4101 | Validate Item | D_F4101ValItem |
Variable standards
Advanced Inventory recommends that you use the following development standards as you create variables.
Naming conventions
Variable IDs should identify the data type and purpose of the variable. Parameters and variables use similar naming conventions.
To make assignments and formulas simple to write and work with, when specifying a variable ID, keep the following considerations in mind.
-
Variable IDs have a maximum length of 20 characters.
-
Variable IDs always have a prefix of "V_".
-
In addition to the automatic prefix, you should assign a prefix for one of the following data types.
-
For a string data type, use "_s".
-
For a date data type, use "_d".
-
For a numeric data type, use "_n".
-
-
When creating a new variable, ensure that it does not duplicate an existing variable.
-
Use camel case between words after the data type prefix.
For examples of variable IDs, refer to the following table.
Variable prefix | Data type prefix | Variable description | Full variable name |
V_ | s | Location | V_sLocation |
V_ | d | TodaysDate | V_dTodaysDate |
V_ | n | QuantityOnHand | V_nTQuantityOnHand |
Parameter standards
Advanced Inventory recommends that you use the following development standards as you create parameters.
Naming conventions
Parameter IDs should identify the data type and purpose of the parameter. Parameters and variables use similar naming conventions.
To make assignments and formulas simple to write and work with, when specifying a parameter ID, keep the following considerations in mind.
-
Parameter IDs have a maximum length of 20 characters.
-
Parameter IDs always have a prefix of "P_".
-
In addition to the automatic prefix, you should assign a prefix for one of the following data types.
-
For a string data type, use "_s".
-
For a date data type, use "_d".
-
For a numeric data type, use "_n".
-
-
When creating a new parameter, ensure that it does not duplicate an existing parameter.
-
Use camel case between words after the data type prefix.
For examples of parameter IDs, refer to the following table.
Parameter prefix | Data type prefix | Parameter description | Full parameter name |
P_ | s | Location | P_sLocation |
P_ | d | TodaysDate | P_dTodaysDate |
P_ | n | QuantityOnHand | P_nTQuantityOnHand |
Service definition standards
Advanced Inventory recommends that you use the following development standards as you create service definitions.
Naming conventions
Service definition ID should identify the system that they are integrating with. They should also include the type of web service with which the definition is interfacing: REST or SOAP, if applicable.
Refer to the following examples.
NS_DSI_CreateBinTransfer_REST
NetSuite RESTful call to create a bin transfer.
WU_GetAlerts
Weather Underground API to get weather alerts.
FedEx_ShipService_processShipment
Fed Ex Ship Service to process a shipment.
FedEx_TrackService_Track
FedEx Tracking Service to receive tracking information.
If you use WSDL to import a service definition, the ID of the service definition is automatically created from the WSDL file. Most of the time, this ID is generic, so Cloud Inventory® strongly recommends that you download and then re-upload the service definition with a more meaningful ID based on the system integrating info.
Example
NS_DSI_SearchCustomers_REST - NetSuite Search Customers (REST OAuth1)
Based on the ID and description, we know the following information about this service definition.
-
For NetSuite
-
Standard product
-
Searching for customers
-
RESTful web service
-
Uses OAuth1 authentication
Data Object standards
Advanced Inventory recommends that you use the following development standards as you create data objects.
Naming conventions
Like service definitions, data object IDs should describe the data being captured and written. If data objects are used in conjunction with a specific web service, use the same naming conventions used in the service definition. For more information, refer to Service definition standards.
Platform display differences
Advanced Inventory apps are supported on different operating systems. Because of this, it is important to remember that some elements look different to end users, based on the device they use to run the app.
Elements that vary between devices include, but are not limited to, buttons, signature boxes, date pickers, and fonts.
Date pickers, for example, vary significantly between Android and iOS. Android devices display a calendar view that allows a user to click on a date. iOS devices display a scrolling view that allows a user to scroll to the day, month, and year to select the date. These operating systems also use and support different fonts.
Platform display differences do not change the functionality and end results of an app. It may be helpful to provide instructions and examples if your user base is split among multiple device types.
Performance considerations
If performance issues occur, they may have an adverse affect on the way the program responds.
Views
When using views, keep the following considerations in mind.
-
In Device DB Tables, views should be used in moderation, as too many views on a table can have an adverse impact on performance.
-
Views are commonly used to join tables together in order to print multiple downloads for display purposes. For example, you can use a view to join the On-hand table and the Item master table to display all inventory on hand in a certain location in addition to displaying the item descriptions.
-
You can also use a view to aggregate functions, such as finding the min/max value or total sum of a column.
-
In an ERP, always work with the DBA at the client to determine if a view is necessary. The same considerations apply for both Device DB Table views and ERP rules.
-
For the most part, trims and substrs are fairly safe to use except in the following instances.
-
BuildTable: Taking data from a large data set (download) and using the BuildTable might create slower performance, as these functions will need to be done on every record of every column used in the BuildTable.
-
Using functions to display the data in data controls like list box, list view, or dropdown list will also slow down performance, as the functions will apply to every record to display.
-
RecordSeek: Using a trim, substring, or function will apply to all records in the seek, which greatly slows the RecordSeek.Note: We recommend seeking for the exact column width of the download or Mobile Client table.
-
Looping
When looping through a record set like a Mobile Client table or download, you should always loop in the following format.
-
Move to first record.
-
Perform intended actions.
-
Move to next record.
-
If found, perform intended actions.
-
Utilize in-line calculations: Val(sss).
Note: We recommend using as few functions as possible in a single in-line statement, because stacking multiple functions tends to slow performance.
Boolean flags
A Boolean flag is a variable used to indicate if a condition is true. For example, boolean flags can indicate whether exit was selected or whether a user selected to continue from a warning. These flags are always set to 1 for Yes/True, and 0 for No/False.
Loading...
There was a problem loading this topic