This chapter covers the following topics:
This document discusses the implementation and use of different bar-code standards within Oracle Mobile Applications. Topics include: overview standards, support within Oracle Mobile applications, configuration, setup and usage. The setup section includes the setup steps for the hardware devices, the mobile server, and the setup within Oracle Applications.
Warehouse applications use labels that comply with Bar coding standards for Automatic identification and data collection (AIDC). Bar code for data collection eliminates manual data collection, improves data collection accuracy, and reduces time and labor. Bar coding standards enable companies to encode, in bar code form, more information than basic product identification. Use this type of supplementary information (such as, Lot Number, Serial Number, License Plate Number, Quantity, etc.) to improve the management of the supply chain. Common application standards for bar coding are ANSI/FACT, EAN/UCC, SPEC2000, HIBCC, EIAJ, etc. Use the following features in Oracle Mobile applications to support bar-coding standards:
Data Field Identifiers (DFIs)
Customized Bar Code Scanning
You use Data Field Identifiers (DFIs) to identify the type of data embedded within a barcode. A DFI usually consists of one to three characters added to the beginning of the data encoded in the barcode. For example, a DFI for a Part Number might be ‘P+.' If the part number encoded in a given barcode is ‘AS54888', the barcode encodes the value ‘P+AS54888' to indicate the barcode is for a part number and the part number is ‘AS54888'.
DFIs help reduce errors caused by scanning the wrong barcode into a field on a mobile device. They also allow fields to be scanned out of order and values to be placed into the appropriate fields.
Oracle Mobile Applications provides DFI support for recognition of barcodes that contain DFIs and out-of-order scanning. You can use DFIs to effectively map ANSI/FACT data identifiers. You can also use DFIs to map Application Identifiers used in UCC/EAN-128 bar code standards.
Oracle Mobile Applications recognizes a DFI included in a barcode and validates it in the proper field. If the DFI is required, a failed DFI validation results in an error message.
You can validate each field on the mobile application against one or more DFIs. If needed, you can optionally flag each field to require a DFI. If a DFI is required, a barcode you scan into this field must have at least one assigned DFI. If the system does not find a DFI, you receive an error message. If a DFI is not required, Oracle validates against a DFI if it is found, but if no DFI is found, the entire value of the barcode is inserted into the field.
Oracle also supports Out-of-Order scanning through DFIs. If you scan a field containing a DFI that corresponds to a field other than current field, the system enters the value of the barcode into the appropriate field. You can then scan the barcode that corresponds to the current field, or scan another DFI identified barcode.
The system validates the value inserted into the Out-of-Order field when you advance to the next field. Because field level validation generally depends on previous fields for validation to occur, you continue on the normal navigation path through the field to complete the transaction.
For example, if you use a mobile device to perform a Miscellaneous Issue of material, first you must scan the issued Part Number. The system validates the scan against a DFI of ‘P+' for the part number. The next scan is a barcode with the value ‘Q+10'. The system determines there is a field on the current page that uses ‘Q+' as a DFI, and places a value ‘10' in the quantity field. You must then scan the issuing subinventory and locator. Then you advance through the quantity field and the quantity validates against the available quantity in the subinventory and locator scanned earlier.
When you scan a barcode, the mobile device prefixes an ASCII control character (the Data Stream Indicator) to the data that transmits to the server. The Oracle Mobile Server recognizes the Data Stream Indicator and searches for a recognizable Data Field Indentifier in the barcode data. The system recognizes a DFI is assigned to a field on the current page. It extracts the value from the barcode and inserts it into the field the DFI represents. The following diagram displays the flow behind Oracle DFI support.
To support DFI, the mobile device must support automatically pre-pending of an arbitrary character to any scanned entry. All the mobile devices certified for use with Oracle Mobile Applications support this functionality. You must configure the Oracle Mobile Server to support DFI scanning.
Finally, the specific Oracle Application the mobile device uses must support DFI functionality. Oracle Mobile Supply Chain Applications, Oracle Inventory Management and Oracle Warehouse Management provide full support for DFI functionality. Check with the specific product user's guide if you are unsure if DFIs are supported.
The setup to enable DFI support involves the following three steps:
Configure the mobile device to prefix an ASCII control character to every scan.
Configure the mobile server to recognize the proper ASCII control character as indicating a scanned entry.
Set up the Applications to recognize DFIs for each field on the mobile windows.
First, configure the mobile device to prefix the Data Stream Indicator to every scan. The Data Stream Indicator must be an ASCII control character (non-printable character). All certified Oracle Mobile Applications devices support this type of configuration. You can configure most scanners by scanning configuration barcodes, navigating to a configuration menu through the device keypad, or by using a remote configuration tool. Refer to the User's guide for the mobile device to determine configuration.
The default Data Stream Indicator is ASCII 28 – File Separator. Use this ASCII control character as the Data Stream Indicator unless there is a reason you cannot use it. You can use any ASCII as the Data Stream Indicator except for the following:
Backspace (8)
Horizontal Tab (9)
Line Feed (10)
Vertical Tab (11)
Form Feed (12)
Carriage Return (13)
Shift Out (14)
Shift In (15)
Escape (27)
After you configure the device to prepend the Data Stream Indicator, you must configure the mobile server to recognize the appropriate Data Stream Indicator. Each device configuration can have a different Data Stream Indicator to support the capabilities of different mobile devices. The configuration setting is located in the device configuration file. The default device configuration setting (default_key.ini) that ships with the mobile server has the Data Stream Indicator set to the default: ASCII 28.
The character the device prepends to a scanned entry must match the entry in the.ini file for the device configuration in order for DFIs to be fully supported.
For more information on mobile device configurations and the configuration.ini file refer to the Oracle Mobile Server User's Guide.
The AK Dictionary stores DFI information as well as the field labels for the mobile windows. If necessary, you can also make changes in the AK Dictionary to the field labels that appear on the mobile windows. To access the AK Dictionary, log on to Oracle Applications on the desktop and access the responsibility AK Developer. Contact your system administrator if you do not have this responsibility.
DFIs may be registered at two different levels – the Attributes level or the Region Items level within the AK Developer Responsibility. Region Items are Attributes assigned to a Region. DFIs registered at the Region Items level take precedence over DFIs registered at the Attribute level.
To register DFIs at the Attributes level, open the Define Attributes window. From that window, you can access the mobile windows fields. You can query attributes by Attribute Name or Label. Enter the DFI string in the Default Varchar2 Value field. The details on the format of the DFI string are as follows: To register DFIs at the Region Items level, you must know the Resource table the specific mobile applications uses (for Oracle Inventory and Oracle Warehouse Management it is INVRESOURCETABLE). You can query the Resource table in the Define Regions window. For example, to query the Oracle Inventory Resource table, query on Region ID = ‘INVRESOURCETABLE.'
Once you find the appropriate Resource table, select Region Items. On the Region Items window, you can view all the AK Region Items used for mobile applications within the table. Locate the field that corresponds to the proper field on the mobile page, and enter the DFI string into the field Default Varchar2 Value.
The DFI String should be entered into the field “Default Varchar2 Value” either on the Attributes level, or the Region Items level. Enter the text in the following format:
“DFI=Q+,q+,Q,q REQ=N”
The above text indicates you can use four DFIs for this field: the characters ‘Q+', ‘q+', ‘Q', and ‘q'. It also indicates this field does not require a DFI. To set the field to required, use the text “REQ=Y” after the DFI list. List DFIs in the proper validation order.
Note: Include DFIs that are subsets of other DFIs after the original DFI. For example, if the DFI ‘Q' is listed before the DFI ‘Q+' and you scan a barcode that uses the DFI ‘Q+', the ‘Q' is removed from the barcode, but the ‘+' remains as part of the field value and an error occurs.
The following chart lists the seeded Data Field Identifiers (DFI) in Oracle Inventory and Oracle Warehouse Management. The seeded identifiers are from the ANSI Data Identifier Standard, document reference ANSI MH10.8.2-1995.
Mobile Prompt | Data Field Information |
---|---|
Card Num | DFI=15K REQ=N |
SO Num | DFI=1K REQ=N |
Sales Order | DFI=1K REQ=N |
From Sub | DFI=1L,20L REQ=N |
Src Sub | DFI=1L,20L REQ=N |
To Sub | DFI=1L,20L REQ=N |
Sub | DFI=1L,20L REQ=N |
Res Sub | DFI=1L,20L REQ=N |
RMA Num | DFI=1R REQ=N |
RMA | DFI=1R REQ=N |
From Loc | DFI=21L REQ=N |
Src Loc | DFI=21L REQ=N |
To Loc | DFI=21L REQ=N |
Locator | DFI=21L REQ=N |
Res Loc | DFI=21L REQ=N |
Location | DFI=2L REQ=N |
Rev | DFI=2P REQ=N |
ASN Num | DFI=2S REQ=N |
ASN | DFI=2S REQ=N |
Deliv UOM | DFI=3Q REQ=N |
Rcpt UOM | DFI=3Q REQ=N |
UOM | DFI=3Q REQ=N |
Res UOM | DFI=3Q REQ=N |
Line Num | DFI=4K REQ=N |
Release | DFI=5K REQ=N |
Rel Num | DFI=5K REQ=N |
LPN | DFI=J REQ=N |
ParentLPN | DFI=J REQ=N |
&Create LPN | DFI=J REQ=N |
Inner LPN | DFI=J REQ=N |
Outer LPN | DFI=J REQ=N |
LPN | DFI=J REQ=N |
Acc LPN | DFI=J REQ=N |
Rej LPN | DFI=J REQ=N |
From LPN | DFI=J REQ=N |
To LPN | DFI=J REQ=N |
Drop LPN | DFI=J REQ=N |
Res LPN | DFI=J REQ=N |
Child LPN | DFI=J REQ=N |
PO Num | DFI=K REQ=N |
Item | DFI=P REQ=N |
Alloc Qty | DFI=Q REQ=N |
Deliv Qty | DFI=Q REQ=N |
Insp Qty | DFI=Q REQ=N |
Lot Qty | DFI=Q REQ=N |
Miss Qty | DFI=Q REQ=N |
Rcpt Qty | DFI=Q REQ=N |
Req Qty | DFI=Q REQ=N |
Ship Qty | DFI=Q REQ=N |
Total Qty | DFI=Q REQ=N |
Ship Qty | DFI=Q REQ=N |
Acc Qty | DFI=Q REQ=N |
Rej Qty | DFI=Q REQ=N |
Ea Lot Qty | DFI=Q REQ=N |
Qty | DFI=Q REQ=N |
Res Qty | DFI=Q REQ=N |
Split Qty | DFI=Q REQ=N |
Ret Qty | DFI=Q REQ=N |
From SN | DFI=S REQ=N |
To SN | DFI=S REQ=N |
SN | DFI=S REQ=N |
Serial | DFI=S REQ=N |
SN | DFI=S REQ=N |
From Lot | DFI=T REQ=N |
To Lot | DFI=T REQ=N |
Lot | DFI=T REQ=N |
Res Lot | DFI=T REQ=N |
Loc | DFI=Z REQ=N |
Customized bar code scanning imbeds user-defined logic to handle scanned input from a bar code scanner. It supports the following scenarios:
Bar coding standards not explicitly supported: These standards could be HIBCC, EIAJ, SPEC2000 etc. You can use the customized bar code scanning feature to write custom logic to handle scanned data when you scan a barcode that complies with one of these standards.
Scanning of concantenated bar code symbol: Most bar coding standards including ANSI/FACT and UCC/EAN-128 allow concatenation of multiple fields to from concatenated bar code symbols. The concatenated bar code symbol may consist of multiple DFIs or AIS, and variable values. If you use customized bar code scanning features, you can write custom logic to handle scanned data from a concatenated bar code symbol. You can encode the customer logic to parse data from the concatenated bar code symbol on populate individual fields on a mobile applications window.
There are two ways to implement user-defined logic to handle scanned input. Customized bar code scanning functionality enables a scanned input to make either a PL/SQL or a java custom class callout. The java custom class is more scaleable and performs better. You must set up the hardware and the mobile server in order to use customized bar code scanning.
Java Call Out: This option involves creation of a java class with embedded user defined logic. Verify this class is compiled with Oracle apps.zip in the classpath. After compilation verify that a file CustomScanManager.class is created. Move this file to $CUSTOM_DIRECTORY/xxx/custom and add $CUSTOM_DIRECTORY to the classpath of your mobile server. $CUSTOM_DIRECTORY, can be any directory on the file system.
PL/SQL Call Out: This option involves modifying the package INV_PREPROCESS_SCAN. This package also takes in the current_page_name and the value scanned and should return the value to replace the scanned value with. However, unlike the java example, this package does not have access to any fields but the current field. It is not possible to modify the values of any other field other than the current field based on the scanned input. It lacks the flexibility provided with the implementation of the above java class file.
The following figure shows a sample concatenated UCC-128 bar code symbol. A single scan of concatenated bar code yields values for multiple data fields and should populate multiple field values in the form. In the following example a single scan of the following bar code should populate the Item, Lot Number, Quantity and Unit of Measure as Kilograms. Standard DFI functionality in Oracle Warehouse Management does not handle this requirement.
Concatenated UCC-128 Bar Code Symbol
The following identifiers are taken from the UCC/EAN-128 application identifiers standards, document reference ANSI/UCC4-1995.
Mobile Prompt | EAN/UCC 128 AI | Data Field Identifier String |
---|---|---|
LPN | 00 | DFI=00 REQ=N |
ParentLPN | 00 | DFI=00 REQ=N |
Create LPN | 00 | DFI=00 REQ=N |
Inner LPN | 00 | DFI=00 REQ=N |
Outer LPN | 00 | DFI=00 REQ=N |
LPN | 00 | DFI=00 REQ=N |
ACC LPN | 00 | DFI=00 REQ=N |
Rej LPN | 00 | DFI=00 REQ=N |
From LPN | 00 | DFI=00 REQ=N |
To LPN | 00 | DFI=00 REQ=N |
Drop LPN | 00 | DFI=00 REQ=N |
Res LPN | 00 | DFI=00 REQ=N |
Child LPN | 00 | DFI=00 REQ=N |
PO Number | 400 | DFI=400 REQ=N |
Item | 01 | DFI=01 REQ=N |
Alloc Qty | 30 | DFI=30 REQ=N |
Deliv Qty | 30 | DFI=30 REQ=N |
Insp. Qty | 30 | DFI=30 REQ=N |
Lot Qty | 30 | DFI=30 REQ=N |
Miss Qty | 30 | DFI=30 REQ=N |
Rcpt Qty | 30 | DFI=30 REQ=N |
Req Qty | 30 | DFI=30 REQ=N |
Ship Qty | 30 | DFI=30 REQ=N |
Total Qty | 30 | DFI=30 REQ=N |
Ship Qty | 30 | DFI=30 REQ=N |
Acc Qty | 30 | DFI=30 REQ=N |
Rej Qty | 30 | DFI=30 REQ=N |
Ea Lot Qty | 30 | DFI=30 REQ=N |
Qty | 30 | DFI=30 REQ=N |
Res Qty | 30 | DFI=30 REQ=N |
Split Qty | 30 | DFI=30 REQ=N |
Ret Qty | 30 | DFI=30 REQ=N |
From SN | 21 | DFI=21 REQ=N |
To SN | 21 | DFI=21 REQ=N |
SN | 21 | DFI=21 REQ=N |
Serial | 21 | DFI=21 REQ=N |
SN | 21 | DFI=21 REQ=N |
From Lot | 10 | DFI=10 REQ=N |
To Lot | 10 | DFI=10 REQ=N |
Res Lot | 10 | DFI=10 REQ=N |
The following is sample Java Code for handling scanned input from a concatenated UCC-128 bar code symbol. Please note the following code has been provided to demonstrate the customizable bar code scanning functionality. Oracle is not responsible for maintaining it. The following code can be modified and distributed without permission from Oracle.
|+======================================================+
| FILENA
ME |
| ScanManager.java |
| DESCRIPTION |
|Class to manage the scans. It will pre-process the | scans. |
| |
| NOTES |
| DEPENDENCIES |
| HISTORY |
| 10-Oct-02 Karun Jain created. |
+=====================================================*/
package xxx.custom;
import oracle.apps.mwa.container.*;
import oracle.apps.mwa.beans.*;
import java.util.*;
import java.sql.*;
/**
* <code>CustomScanManager</code> is the customizable
* call out to pre-process a scanned barcode.
* It has reference to the current MWA Session, and the
* page the scan was performed on. One can access the
* database session using the MWA
* session passed in. Please refer to the MWA API
* documentation or the WMS Customization document for
* more information and ways to customize the class.
**/
public class CustomScanManager {
private void CustomScanManager() {};
public static boolean isInputableField(FieldBean f) {
if ((f instanceof InputableFieldBean) && (((InputableFieldBean) f).isEditable()))
return true;
else
return false;
}
/**
* This is a customizable method.
**/
/**
* In this example we have scanned a concatenated UCC128
* barcode which has Item, quantity, lot_number and
* lot_quantity.
* With one scan we want to populate all the above fields
* on the PO Receipt page.
* It returns the value to be set for the current field:
* in our example is item.
**/
// curtPage passes the current MWA Page
// curtSession passes the java session
// val has the value that was scanned
public static String processScan(oracle.apps.mwa.container.Session curtSession,
oracle.apps.mwa.beans.PageBean curtPage,
java.lang.String val) {
// This will log a message in the server trace file if // you have the MWA server running in the trace mode.
// Pleade preceede your messages with CTM.
FileLogger.getSystemLogger().trace("CTM: Pre-preocessing the scan");
FieldBean curtBean = curtPage.getCurrentFieldBean();
if (curtBean instanceof oracle.apps.inv.lov.server.ItemLOV) {
int itemFieldIndex = curtPage.getCurrentFieldIndex();
String itemValue = val;
String [] curtFieldDFIs = null;
int intemDFILength = 0;
if (isInputableField(curtBean)) {
curtFieldDFIs = ((InputableFieldBean)curtBean).getDFIs();
int itemDFILength = 0;
if (curtFieldDFIs != null) {
// if prefix of value is in curt field DFI, strip it,
// and setFieldValue
for (int i=0; i < curtFieldDFIs.length; i++) {
int x = itemValue.indexOf(curtFieldDFIs[i]);
if (x == 0) {
// found a DFI in the value, let's strip it
itemDFILength = curtFieldDFIs[i].length();
FileLogger.getSystemLogger().trace("CTM: found matching Item DFI "+ curtFieldDFIs[i]);
FileLogger.getSystemLogger().trace("CTM: Item DFI Length: "+ itemDFILength);
break;
}
}
// After stripping the DFI only the first 14 characters // are for item Process the remaining characters for the // remaining fields
if (itemValue.length() > (14+itemDFILength)) {
Vector fieldBeanList = curtPage.getFieldBeanList();
int qtyFieldIndex = 0;
int lotNumFieldIndex = 0;
int lotQtyFieldIndex = 0;
// Get the index for the other three fields from the
// list of fields
for (int i=itemFieldIndex; i<fieldBeanList.size(); i++) {
String name = ((FieldBean)fieldBeanList.elementAt(i)).getName();
if (name != null && name.equals("INV.QTY"))
qtyFieldIndex = i;
if (name != null && name.equals("INV.LOT"))
lotNumFieldIndex = i;
if (name != null && name.equals("INV.LOT_QTY"))
lotQtyFieldIndex = i;
}
// Get the value for the item field
String remainingValue = itemValue.substring(14+itemDFILength);
itemValue = itemValue.substring(0,(14+itemDFILength));
FileLogger.getSystemLogger().trace("CTM: Item value: "+ itemValue);
FileLogger.getSystemLogger().trace("CTM: Remaining value: "+ remainingValue);
String qtyValue = "";
// Found qty field so set the value for the quantity
if (qtyFieldIndex > 0) {
FileLogger.getSystemLogger().trace("CTM: Found the qty field");
boolean doneQty = false;
String [] qtyFieldDFIs = null;
FieldBean qtyField = ((FieldBean)(fieldBeanList.elementAt(qtyFieldIndex)));
if (isInputableField(qtyField)) {
qtyFieldDFIs = ((InputableFieldBean)qtyField).getDFIs();
if (qtyFieldDFIs != null) {
// if prefix of value is in curt field DFI, strip it,
// and setFieldValue
FileLogger.getSystemLogger().trace("CTM: Got the dfi for qty fld");
for (int j=0; j < qtyFieldDFIs.length; j++) {
int x = remainingValue.indexOf(qtyFieldDFIs[j]);
FileLogger.getSystemLogger().trace("CTM: "+j+"th DFI:"+qtyFieldDFIs[j]);
if (x == 0) {
// found a DFI in the value, let's strip it
qtyValue =
remainingValue.substring(x+qtyFieldDFIs[j].length(),
x+qtyFieldDFIs[j].length()+6);
((InputableFieldBean)qtyField).setValue(qtyValue);
FileLogger.getSystemLogger().trace("CTM: Qty value:"+qtyValue);
if (remainingValue.length() >
(qtyFieldDFIs[j].length()+6)) {
doneQty = true;
remainingValue =
remainingValue.substring(x+qtyFieldDFIs[j].length()+6);
FileLogger.getSystemLogger().trace("CTM: Remaining value:"+remainingValue);
} else remainingValue = "";
break;
}
}
}
}
// Set the value for the lot number and lot qty field
if (doneQty && lotNumFieldIndex > 0) {
FileLogger.getSystemLogger().trace("CTM: Found the lot Num field");
((InputableFieldBean)(fieldBeanList.elementAt(lotQtyFieldIndex))).setValue(qtyValue);
FieldBean lotNumField = ((FieldBean)(fieldBeanList.elementAt(lotNumFieldIndex)));
String [] lotNumFieldDFIs = null;
if (isInputableField(lotNumField)) {
lotNumFieldDFIs = ((InputableFieldBean)lotNumField).getDFIs();
if (lotNumFieldDFIs != null) {
// if prefix of value is in curt field DFI, strip it,
// and setFieldValue
for (int j=0; j < qtyFieldDFIs.length; j++) {
int x = remainingValue.indexOf(lotNumFieldDFIs[j]);
if (x == 0) {
// found a DFI in the value, let's strip it
String lotNumValue =
remainingValue.substring(x+lotNumFieldDFIs[j].length());
((InputableFieldBean)lotNumField).setValue(lotNumValue);
FileLogger.getSystemLogger().trace("CTM: Lot value:"+lotNumValue);
}
}
}
}
}
}
}
}
}
return itemValue;
} else {
return val;
}
}
}