You are on page 1of 19

Oracle Warehouse Management

Label Customization
An Oracle Topical Essay
October 2002
Oracle Warehouse Management
Label Customization

LABEL CUSTOMIZATION
Oracle Warehouse Management System has a complete label printing solution where any number of
different label types can be printed as part of any number of different business flows. The different
label types have hundreds of different fields that can be selected for inclusion in each label. However,
sometimes the data that must be included on a particular label is not available as one of the standard
fields provided by Oracle WMS. In these cases, customization is often necessary to get exactly the
label required.
This document outlines several customization options with full examples. As customization should be
avoided as much as possible, however, several additional features often available in the third party
label printing software and the label printing hardware will also be described. This document assumes
knowledge of standard label printing provided by Oracle WMS.

Labeling Overview
Oracle WMS produces xml files as part of a transaction or event, such as a purchase order receipt,
pick confirmation, work order completion, or license plate generation. Oftentimes, the types of labels
that might be required during certain transactions, and the source of the data for those labels, are
identical for several different transactions. Transactions and events for which the labeling
requirements are similar are grouped into business flows.
These business flows are then associated with label types. The type of data that included in each label
differentiates the label types. For instance, the material label type includes all the attributes about an
item, such as item description and weight, while a shipping label includes details about the sales order
and customer for which an order is being shipped. Only some of the label types are applicable to each
business flow. For instance, the information to print a shipping label is not available during a
purchase order receipt, while a manufacturing label is generally not printed during a shipment
transaction. WMS allows the user to assign any of the label types to any of the business flows within
those restrictions, and furthermore, the assignments can be specific to a user or responsibility, or made
at several other levels.
While the label type identifies the type of data that is available to each label, a label format identifies
the exact fields that are included in each label, as well as the name to assign to each of those fields that
the third-party label integration software will identify. WMS uses the Rules Engine to determine
which label format among several to print when a particular label type is required. WMS produces an
XML file (or an XML stream to a API) with the label format name, the data and variable names
indicated on the label format, and places it in a specific directory. A printer is also specified in the
XML file, and is specified in WMS by way of an assignment to one of several levels such as the user
or subinventory.
The third-party label integration software monitors that label directory (or by way of a synchronous
API) for XML files, and converts the XML to a printer-readable format. The actual layout of each
format, including text font, barcode and barcode symbology, and media size, are all defined in this
third-party software. The label formats are linked to the XML data by way of common label format
names, and common variable names that define each individual field.
The following sample XML file shows the formatting Oracle WMS produces. The complete XML
DTD, as well as additional examples and information about label formats, can be found in the WMS
Implementation Guide.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE labels SYSTEM "label.dtd">
<labels _FORMAT ="Material" _QUANTITY="1" _PRINTERNAME="Printer 1" _JOBNAME="LBL101">
<label>
<variable name= "ITEM">AS54888</variable>
<variable name= "ITEMDESC">Desktop</variable>
<variable name= "LOT">10292</variable>
<variable name= "QTY">2</variable>
<variable name= "UOM">Ea</variable>
</label>
</labels>

Mobile Supply Chain Applications provides identical labeling support with several exceptions.
Instead of using the Rules Engine to select among the many different label formats of a given label
type, a default label format is indicated and MSCA always selects this default format. In addition,
some of the label formats, and some of the fields on other label formats, are not available without
WMS. However, the links between transactions, business flows, label types, and label formats,
remains the same.

Alternatives to Customization
While customization may sometimes be the only approach available to provide precisely the label
required for a given business scenario, there may often be alternatives to customization by either
changing the business processes surrounding the label printing, or using features available in the third-
party label printing software. Customization has many hidden costs, such as additional support and
the difficultly in keeping current with the latest Oracle upgrades, and thus should be considered only if
all other options are exhausted.
The sections below discuss several business requirements that can be met by features that are often
available in the third party label printing software or the printing hardware. Note that each software
package and printer hardware is different, and thus you should refer to the users guides of the
respective components to understand if the feature is available.

Multiple Copies

Although Oracle WMS allows the user to enter the label quantity during manual label printing
requests, WMS does not have a facility for controlling the number of copies of a label to print when
printing is triggered automatically during a business flow. A common business requirement is for
multiple copies of a particular label format to be printed. This can often be controlled by
configuration of the actual printer hardware, so that each request sent to the printer produces multiple
identical labels. In addition, some software allows the quantity to be manipulated, so that the number
of copies can be controlled by a set of conditions specified in the software. Manual print requests can
also be made to get additional copies of a particular label.
Field Manipulation

Often, the data that must be printed on the label is not a single data element or field available in WMS,
but rather, a product of several component fields. A common requirement is to concatenate multiple
fields into a single barcode, merging quantity and unit-of-measure, for instance. Or, with more dense
barcodes such as PDF417, dozens of fields can be concatenated into a single barcode with certain
characters delimiting where each data element ends and the next one begins. Mathematical
manipulation of the data may also be required; for instance, the width and length of an item may be
stored as item or lot attributes, but the data that may be required on the label is the area (width
multiplied by length) instead. Most label printing packages offer these basic field manipulation tools
as part of the label format design.

Selectively Printing Labels

A certain label type may be only occasionally required as part of a business flow. For instance, during
a purchase order receipt, an LPN Summary label may always be required, but a Material label may
only be required if the material is hazardous. Because WMS associates a set of label types with a
business flow, all of the labels will be printed each time that business flow is triggered. However, a
“dummy” label format with no label fields can be defined for the label type. The Rules Engine can be
used to select this dummy format whenever no label should be printed. In this way, complex logic can
be defined to control exactly when a given label type associated with a business flow should be
printed.

Images and Icons

The label format layout tools allow an image, trademark, or other non-text object to be included in
label formats. For instance, an organization may require that all shipping labels be printed with the
company’s trademark in one corner. In addition, multiple formats with different images can be
defined, and the Rules Engine can be leveraged to select among the various formats.

Multiple Formats for MSCA

The primary difference between labeling support for MSCA and for WMS is that WMS provides the
Rules Engine to select the appropriate label format among many, while MSCA always selects the
same default label format for a given label type. However, many MSCA customers still have the
requirement to print various formats without requiring the additional features a full-blown WMS
solution entails. Often, the third-party software includes logic that can make label format decisions
based on the data included in the source XML. In this way, one label format can be defined as the
default in Oracle that includes all the superset of all the fields the “real” label formats will require.
Then the format selection logic can be encoded in the third-party software, based off of any of the
attributes provided in the XML.

Change Business Processes

Sometimes, the data that is required for a label is not available at the first moment a label could be
printed, but may be available at a later point. In these cases, a temporary label with a subset of the
required data could be printed, while a new complete label could be printed later. While this requires
reprinting and re-labeling, it may prove less onerous then customizing the application.
For instance, a customer-specific label that includes details such as the customer name, customer
purchase order, and customer item number, may be required for a pallet of material that is
manufactured specifically for that customer. The original business process may call for that label to
be produced as part of the manufacturing completion process. However, the customer specific data is
not available as standard functionality in any of the labels that can be produced at completion.
All those fields are available on the Shipping Contents label type, but that label is only available as
part of the pick confirmation or ship confirmation business flow, or via a manual reprint request after
an LPN has been loaded if Direct Ship is being used. A temporary label to identify the LPN can be
used for the pallet and printed as part of the manufacturing completion business flow, while the more
complete Shipping Contents label could be printed automatically as part of the pick confirmation
business flow. In this way, via an additional labeling operation, customization can be completely
avoided.

Customization Strategies
If the alternatives to customization discussed above still are not enough to support the label printing
needs, then there are three main avenues for customization that can be used independently or in
combination, and can also be used in concert with the features described above.
The label printing solution allows many of the flexfields to be included in the labels, so the application
can be customized to populate these flexfields prior to printing. The customization can be made as
part of a database trigger or a custom PL/SQL package. While direct customizations to the application
require careful maintenance to ensure that patches do not overwrite the custom code, this approach
allows the flexfield data to be easily used in label format selection rules, as well as making the data in
the flexfield available for other business processes. This is the best approach when the structure of the
standard labels meets the requirements, but additional data is required.
Another approach is to use a light-weight “pre-processor” to intercept the XML files before they are
picked up by the label printing software. The pre-processor can perform more complex data
manipulation than may be available in the third-party software. In addition, database queries can be
embedded in the pre-processor so that data not initially included in the XML can be added. This
approach can split one label into many, or aggregate many labels into one, and is the best
customization approach when the general structure of the standard labels provided by WMS cannot
meet the labeling requirements. Note that this customization does not involve modifying the Oracle
application at all and so patching and upgrading concerns become less of an issue. However, as an
independent program, it must still be maintained and monitored to ensure that the process is kept
running.
Finally, if labels are required during business flows or events that do not already support label
printing, the label printing API can be called by custom code. Note that this requires direct
customization to the application, and thus is subject to the same patching and maintenance issues as
the flexfield customizations.
Note that direct customization of the label printing code, such as modifying the queries used to gather
the data, seeding additional fields, or adding an additional label type, is not recommended. However,
with a combination of the three approaches above, any label can be printed at any time with any data,
and the label structure can be drastically different from the original label produced by Oracle WMS.

Populating Flexfields
All of the flexfields on tables for which data is available for the labels have also been included for use
as label fields. For instance, the Shipping Content label includes information about the sales order, so
any of the flexfields related to the sales order (order header, order line, pricing attributes, for instance)
can also be included on the label without customizing the label code. Data can be populated in
flexfields directly by a user, or via a trigger that is dependent on other sections of code.
For instance, suppose particular license plates are manually reserved to specific customers via the Item
Reservations form. These license plates are then labeled with the customer specific labels that include
the customer name and order number. By labeling the license plates while they are still in inventory,
prior to pick confirmation, the picking and shipping process can be simplified because no additional
labeling steps may be required as part of the outbound flows. But the customer data is not available
on any labels prior to pick confirmation. An extension to the Item Reservations form could be written
that does the following whenever a reservation is manually created to the LPN detail level:
• Populate Attribute1 on the LPN Flexfield with the customer name
• Populate Attribute2 on the LPN Flexfield with order number
Additional attributes could be populated as necessary to capture the shipping address, the customer
purchase order number, and so forth. These attributes can then be referred to in the label format
definitions without any customizations to the label printing routines. Then, either the new customer
specific license plate labels can be printed either via a user-initiated manual label reprint request, or
automatically if the customization directly calls the label printing APIs. Note that by populating the
flexfields with this additional data, the Rules Engine can also be leveraged to select the correct label
format based on the customer, ship to address, or any other data populated in the flexfields.
As this type of customization requires directly modifying the forms to populate additional data into
particular flexfields, it carries the standard risks that patches may overwrite the customizations, and
future releases may require re-engineering of the customization in that the business flows surrounding
a particular form may change.

Label Pre-Processor

Oracle WMS drops an XML file in a pre-specified directory, and the third-party label printing
software picks up this file from the same directory and produces a label. However, an additional
processing step could be inserted between Oracle dropping off the file and the printing software
picking up the file. This step could modify the structure of the label in complex ways, potentially
aggregating different labels into one label, adding new fields that could not be made available even in
flexfields as described above, or performing operations on the data included in the label that the label
integration software is not capable of performing.
Because an XML file is simply a plain-text file with a special formatting structure, any text
manipulation tools be used to monitor a pre-specified directory. This job would monitor the directory
into which Oracle drops the XML files, conditionally change the XML file, and then move it to
another directory that the label integration software is monitoring. This pre-processor could be written
in Java, C, or any other programming language. The examples developed below, however, show how
the text manipulation utilities available in Unix can be built into a shell script to do the pre-processing.
This process introduces an additional layer of complexity to the label printing process, and increases
the latency between when the request is made and when the final label is produced. The label pre-
processor must be monitored, external to the Oracle application, to ensure that it is running; from the
WMS perspective, after the label is dropped in the initial directory, the work is complete. However,
this type of customization can be incredibly flexible and powerful in modeling complex requirements
that WMS does not currently support. In addition, Oracle upgrades and patches do not interfere with
the customization.
Three examples will be developed below, each starting from the basic business requirement and
ending with the shell script that will modify the XML. A fourth example, and several different
approaches to tackle it, will also be discussed. These examples illustrate the flexibility this method of
customization provides and the design process that needs to precede the customization. However, this
section does not intend to be a programming guide for shell scripts, and no guarantee is made as to the
completeness, error handling, or performance; they are to be used as guidelines for a full design,
development, and testing process. Setting up the scripts to monitor a directory will be discussed, and
finally, performance considerations will be described.

Simple Field Modification


Two options by which to print multiple copies of a label were discussed above: either via a setting on
the printer hardware, or via a setting in the third party integration software. However, a static setting
of the number of copies to print may still not meet the business requirements. The following scenario
models the case where the quantity of a particular label to print depends on attributes of the item.
An organization that deals with large items may require multiple label copies, but only if the item
exceeds a certain size limit. Specifically, if the length of an item is four or more feet, then two copies
of the label should be printed. However, if the item is less than four feet long, one copy of the label
will suffice. The Rules Engine will be used to select a different label format of the Material label type
if the item is greater than four feet. The pre-processor will change the quantity of labels to print to 2 if
the label format is LG_MATERIAL.
Note that the decision criteria of item length could have simply been included in the label format, and
then the pre-processor could base the label quantity directly from that length. However, this example
illustrates how the Rules Engine can be used to extract some of the potentially complex logic from the
custom pre-processor, and place it into the Oracle-supported Rules Engine.
#!/bin/sh
#################################################
# This shell script has been created to
# demonstrate the extensibility of Oracle WMS
# labeling solution. It is not delivered as a
# standard Oracle product. Please feel free to
# edit or modify as needed.
#
# Author: David Wertheimer
#################################################
# This script iterates through each xml file in
# the source directory, replacing _QUANTITY="1"
# with _QUANTITY="2" if the file includes the
# text LG_MATERIAL and moving the new file to
# the destination directory. If the file does
# not contain the text LG_MATERIAL, it is moved
# to the destination directory unchanged.
#################################################
# Enter source / destination directories here.
# - SrcDir must be the directory where Oracle
# drops the xml files, identified by the
# profile option WMS: Label Output Directory
# - DestDir must be the directory in which the
# third party label integration software
# expects to find the xml files.
#################################################
SrcDir=/home/dlwerthe/work/labels/test_in/
DestDir=/home/dlwerthe/work/labels/test_out/
#################################################
# For each file in the source directory ending with *.xml
for file in ${SrcDir}*.xml
do
# The new file will have the same file name in the dest directory
ofile=$DestDir/`basename $file`
# If the text LG_MATERIAL is found in the label
if [ `grep '"LG_MATERIAL"' $file|wc -l` -eq 1 ]
then
# Copy the label to the destination, replacing the quantity
sed s/'_QUANTITY="1"'/'_QUANTITY="2"'/g < $file > $ofile
# Remove the original label file
rm $file
else
# Otherwise, move the label to the destination unchanged
mv $file $ofile
fi
done

Creating Labels with Custom Data


There are often very specific requirements for manufacturing labels to help ensure that the finished
product can be traced back to exact job that created the material, and even more specifically, the
sequence in which the material was finished. The following scenario illustrates how one xml file
produced by WMS can be used to create many related labels.
A particular consumer packaging plant cuts many small rolls, or “bobbins” of aluminum foil from a
single large roll. As the roll is wound on to the bobbins, it is cut every 30 feet. Each of these cuts is
numbered sequentially with a number called the “set”, starting with 1. The roll is much wider than the
bobbin, and so the roll is slit as it is wrapped around several bobbins at a time. Each of these slits,
from left to right, is called a “cut”, and is similarly numbered from 1. Each bobbin needs one label,
and that label must include the set and cut in the format SET-CUT. If the roll were completely
unwound and laying on a flat surface, this could be thought of as drawing a grid on the foil, and
numbering the sections to be cut from 1-1 to, perhaps, 99-99. The number of cuts to print is
determined by the width of the bobbin in comparison to the width of the component roll, while the
number of sets is determined by the number of cuts required and the quantity on the job. Both of these
widths, as well as the job quantity, need to be included in the original label produced by WMS so that
the pre-processor knows how to number the bobbin labels.
Standard label printing features provide for printing manufacturing labels at several points: as part of
the completion transaction, as a separate user-initiated “prepack” process, integrated to move
transactions for flow manufacturing, and during a component issue if the component pick release
process is used. Of course, none of these labels would have the set and cut data printed on it
automatically, but one of these manufacturing-related labels must be selected for customization.
Neither the completion label nor the label printed during prepack have details about the job, so the
required data to calculate the set and cut could not be available, even on flexfields. The flow labels
are not available for discrete jobs, so that option is discarded. The label produced during the task-
based material issue is, however, available for discrete jobs, and its also printed automatically before
the job begins, so the labels will also be available at the right time, as bobbins are being wound.
A special format of the WIP Contents label must be defined. This label can be tied to the WIP Pick
Drop business flow, so that whenever a manufacturing task has been completed and material issued to
the job, the label will be printed. The Rules Engine can be used to selectively determine when this
format, and thus all the bobbin labels, should be triggered. Specifically, it should print this format,
named, say, BOBBIN, for only the roll component. The format must include the job quantity
(JOB_QTY), the roll width populated in an item flexfield (ROLL_WIDTH), and the bobbin width
populated in a job flexfield (BOBBIN_WIDTH). These flexfields could be populated manually by a
user, or automatically as part of a flexfield customization as documented above.
#!/bin/sh
#################################################
# This shell script has been created to
# demonstrate the extensibility of Oracle WMS
# labeling solution. It is not delivered as a
# standard Oracle product. Please feel free to
# edit or modify as needed.
#
# Author: David Wertheimer
#################################################
# This script iterates through each xml file in
# the source directory, modifying only labels
# of format BOBBIN. If the label includes the
# text BOBBIN, the single label in the file will
# be replaced with QTY labels (where QTY is
# indicated in the xml) in a single xml file in
# the destination directory. All the fields in
# the original source label will be carried
# unchanged to the destination label with the
# following exceptions:
#
# - JOB_QTY will be removed
# - ROLL_WIDTH will be removed
# - BOBBIN_WIDTH will be removed
# - SET will be added
# - CUT will be added
#
# * CUT will iterate from 1 to
# floor(ROLL_WIDTH / BOBBIN_WIDTH) and be
# incremented with each consecutive label
# * SET will increase from 1 to
# ceil(JOB_QTY/floor(ROLL_WIDTH / BOBBIN_WIDTH))
# and be incremented after each
# floor(ROLL_WIDTH / BOBBIN_WIDTH) labels
#
#
# If the file does not contain the text BOBBIN,
# it is moved to the destination directory
# unchanged.
#################################################
# Enter source / destination directories here.
# - SrcDir must be the directory where Oracle
# drops the xml files, identified by the
# profile option WMS: Label Output Directory
# - DestDir must be the directory in which the
# third party label integration software
# expects to find the xml files.
#################################################
SrcDir=/home/dlwerthe/work/labels/test_in/
DestDir=/home/dlwerthe/work/labels/test_out/
#################################################
for file in ${SrcDir}*.xml
do

# The new file will have the same file name in the dest directory
ofile=$DestDir/`basename $file`

# If the text BOBBIN is found in the label


if [ `grep '"BOBBIN"' $file|wc -l` -eq 1 ]
then

# Extract the three fields (QTY, BOBBIN_WIDTH, ROLL_WIDTH) from xml


QTY=`grep '"JOB_QTY"' $file|sed 's/<\/variable>//g'|sed 's/<variable name= "JOB_QTY">//g'`
BOB=`grep '"BOBBIN_WIDTH"' $file|sed 's/<\/variable>//g'|sed 's/<variable name= "BOBBIN_WIDTH">//g'`
ROL=`grep '"ROLL_WIDTH"' $file|sed 's/<\/variable>//g'|sed 's/<variable name= "ROLL_WIDTH">//g'`

# Calculate the maximum cut and maximum set based on the widths and quantity
MAX_CUT=`expr $ROL / $BOB`
MAX_SET=`expr $QTY / $MAX_CUT`
if [ `expr $MAX_CUT \* $MAX_SET` -lt $QTY ]
then
MAX_SET=`expr $MAX_SET + 1`
fi

# Initialize counters
LBLCTR=1
SET=1
CUT=1

# Extract the part of the label to be repeated into body.tmp


# by removing the quantity and width variables, the </labels> line
# and the three header lines at the top of the label
LABEL=`sed /JOB_QTY/d $file|sed /ROLL_WIDTH/d|sed /BOBBIN_WIDTH/d>label.tmp`
sed /xml/d label.tmp|sed /DOCTYPE/d|sed /labels/d|sed /'<\/label>'/d>body.tmp

# Place the three header lines in the top of the new label
sed 3q $file>$ofile

# Repeat for each bobbin to print


while [ $LBLCTR -le $QTY ]
do

# Concatenate the label body onto the new label file


cat body.tmp>>$ofile

# Append the SET and CUT to the label file


printf "<variable name=\"SET\">$SET</variable>\n">>$ofile
printf "<variable name=\"CUT\">$CUT</variable>\n">>$ofile
printf "</label>\n">>$ofile
# Determine the new SET and CUT
LBLCTR=`expr $LBLCTR + 1`
CUT=`expr $CUT + 1`
if [ $CUT -gt $MAX_CUT ]
then
CUT=1
SET=`expr $SET + 1`
fi
done

# Close the label file with the </labels> tag


printf "</labels>\n">>$ofile

# Remove the .tmp files and the old label file


rm label.tmp
rm body.tmp
rm $file

# Otherwise, move the label to the destination unchanged


else
mv $file $ofile
fi
done

Including Additional Data Sources


Populating the flexfields may not be feasible if there are more fields that must be added than there are
flexfields available, or if the data that needs to be populated on the label via the flexfields can be
modified via many different forms so that it would be more complex to modify all these areas than
just simply querying for the required data as an extension to the printing process.
Continuing with the example above for the bobbin labels, the bobbins are manufactured for a
particular customer, Acme Industries. The job is tied to that customer by way of a material
reservation. Instead of printing the manufacturer’s part number of each bobbin, the customer part
number should be printed, if available. The Rules Engine will be used to ensure that the label format
that is linked to the customization is selected only when the customer tied to the work order is Acme
Industries. The same WIP Contents label will be customized so that the set, cut, and customer item
fields are included. However, rather than relying on flexfields to be populated to get the roll width,
bobbin width, and customer item, direct queries to the database will be used to get this data.
Therefore, no customizations need be made directly to the application.
#!/bin/sh
#################################################
# This shell script has been created to
# demonstrate the extensibility of Oracle WMS
# labeling solution. It is not delivered as a
# standard Oracle product. Please feel free to
# edit or modify as needed.
#
# Author: David Wertheimer
#################################################
# This script iterates through each xml file in
# the source directory, modifying only labels
# of format BOBBIN. If the label includes the
# text BOBBIN, the single label in the file will
# be replaced with QTY labels (where QTY is
# indicated in the xml) in a single xml file in
# the destination directory. All the fields in
# the original source label will be carried
# unchanged to the destination label with the
# following exceptions:
#
# - JOB_NAME will be removed
# - COMP_ITEM will be removed
# - SET will be added
# - CUT will be added
# - FG_ITEM will be added
#
# * CUT will iterate from 1 to
# floor(ROLL_WIDTH / BOBBIN_WIDTH) and be
# incremented with each consecutive label
# * SET will increase from 1 to
# ceil(JOB_QTY/floor(ROLL_WIDTH / BOBBIN_WIDTH))
# and be incremented after each
# floor(ROLL_WIDTH / BOBBIN_WIDTH) labels
#
# ROLL_WIDTH will be directly queried as the
# UNIT_WIDTH on the COMP_ITEM. BOBBIN_WIDTH
# will be directly queried as the UNIT_WIDTH on
# the finished good associated with the job.
#
# In addition, if the job is entirely reserved
# to a single customer, and the sales order
# indicates the customer item, rather than the
# internal item number, then FG_ITEM will be
# populated with the customer item.
# - Assumption: job must be entirely reserved to
# single customer; otherwise customer specific
# data will not be included in label.
# - Assumption: the order must have been entered
# with the customer item.
#
# If the file does not contain the text BOBBIN,
# it is moved to the destination directory
# unchanged.
#################################################
# Configure script here.
# - SrcDir must be the directory where Oracle
# drops the xml files, identified by the
# profile option WMS: Label Output Directory
# - DestDir must be the directory in which the
# third party label integration software
# - Instance is the database name to which
# sqlplus should connect
# - User/Pswd are the user name and password
# to the instance.
# Note that this script must be run in an envt
# that has access to sqlplus and the database
# so that environment variables may need to be
# set.
#################################################
SrcDir=/home/dlwerthe/work/labels/test_in/
DestDir=/home/dlwerthe/work/labels/test_out/
User=apps
Pswd=apps
Instance=wmsdev
#################################################
for file in ${SrcDir}*.xml
do

# The new file will have the same file name in the dest directory
ofile=$DestDir/`basename $file`

# If the text BOBBIN is found in the label


if [ `grep '"BOBBIN"' $file|wc -l` -eq 1 ]
then

# Extract two fields (JOB_NAME, COMP_ITEM) from xml


JOB=`grep '"JOB_NAME"' $file|sed 's/<\/variable>//g'|sed 's/<variable name= "JOB_NAME">//g'`
COMP=`grep '"COMP_ITEM"' $file|sed 's/<\/variable>//g'|sed 's/<variable name= "COMP_ITEM">//g'`

# Extract the bobbin width, roll width, & customer item into
SQLOUT=`sqlplus $User/$Pswd@$Instance << EOF
set verify on
set feedback on
set serveroutput on size 200000
select '|',msifg.unit_width as bobbin_width, '|',
nvl(customer_item_number,msifg.segment1) as item, '|'
from wip_entities we,
mtl_reservations mr,
mtl_sales_orders mso,
oe_order_headers_all ooh,
wip_discrete_jobs wdj,
mtl_system_items msifg,
oe_order_lines_all ool,
mtl_customer_items mci
where wip_entity_name = '$JOB'
and wdj.wip_entity_id = we.wip_entity_id
and we.wip_entity_id = mr.supply_source_header_id
and mr.supply_source_type_id = 5
and mr.demand_source_type_id = 2
and mr.demand_source_header_id = mso.sales_order_id
and mso.segment1 = ooh.order_number
and wdj.start_quantity = mr.reservation_quantity
and wdj.primary_item_id = msifg.inventory_item_id
and wdj.organization_id = msifg.organization_id
and ool.header_id = ooh.header_id
and ool.ordered_item_id = mci.customer_item_id (+);
select '|',wdj.start_quantity as job_qty, '|'
from wip_entities we,
wip_discrete_jobs wdj
where wip_entity_name = '$JOB'
and wdj.wip_entity_id = we.wip_entity_id;
select '|',unit_width as roll_width,'|'
from mtl_system_items msi, wip_entities we
where segment1 = '$COMP'
and we.organization_id = msi.organization_id
and we.wip_entity_name = '$JOB';
EOF`
echo "$SQLOUT" > label_sql.tmp
BOB=`cut -f2 -s -d"|" label_sql.tmp|sed 1q|sed 1q|sed s/" "//g|tr -d '\011'`
FG_ITEM=`cut -f3 -s -d"|" label_sql.tmp|sed 1q|sed s/" "//g|tr -d '\011'`
QTY=`cut -f2 -s -d"|" label_sql.tmp|tail -2| head -1|sed 1q|sed s/" "//g|tr -d '\011'`
ROL=`cut -f2 -s -d"|" label_sql.tmp|tail -1|sed 1q|sed s/" "//g|tr -d '\011'`
rm label_sql.tmp
# Calculate the maximum cut and maximum set based on the widths and quantity
MAX_CUT=`expr $ROL / $BOB`
MAX_SET=`expr $QTY / $MAX_CUT`
if [ `expr $MAX_CUT \* $MAX_SET` -lt $QTY ]
then
MAX_SET=`expr $MAX_SET + 1`
fi

# Initialize counters
LBLCTR=1
SET=1
CUT=1

# Extract the part of the label to be repeated into body.tmp


# by removing the JOB_NAME & COMP_ITEM variables, the </labels> line
# and the three header lines at the top of the label
LABEL=`sed /JOB_QTY/d $file|sed /JOB_NAME/d|sed /COMP_ITEM/d>label.tmp`
sed /xml/d label.tmp|sed /DOCTYPE/d|sed /labels/d|sed /'<\/label>'/d>body.tmp

# Place the three header lines in the top of the new label
sed 3q $file>$ofile

# Repeat for each bobbin to print


while [ $LBLCTR -le $QTY ]
do

# Concatenate the label body onto the new label file


cat body.tmp>>$ofile

# Append the SET and CUT to the label file


printf "<variable name=\"SET\">$SET</variable>\n">>$ofile
printf "<variable name=\"CUT\">$CUT</variable>\n">>$ofile
printf "<variable name=\"FG_ITEM\">$FG_ITEM</variable>\n">>$ofile
printf "</label>\n">>$ofile

# Determine the new SET and CUT


LBLCTR=`expr $LBLCTR + 1`
CUT=`expr $CUT + 1`
if [ $CUT -gt $MAX_CUT ]
then
CUT=1
SET=`expr $SET + 1`
fi
done

# Close the label file with the </labels> tag


printf "</labels>\n">>$ofile

# Remove the .tmp files and the old label file


rm label.tmp
rm body.tmp
rm $file

# Otherwise, move the label to the destination unchanged


else
mv $file $ofile
fi

done

Working with Multi-Record Formats


Two of the label types produced by WMS are potentially multi-record labels, in that a single label
may be produced for potentially many items. Specifically, the Shipping Content and LPN Summary
label types can print one label for multiple items and item lots contained in a single license plate.
There are several business requirements for several records of data on a single label that cannot be
easily produced by these two multi-record labels, however, such as the following:
• Printing multiple serials on a single label
• Sorting the records on a multi-record label by the lot expiration date, quantity, or some other
field
• Providing some types of aggregate statistics about the license plate, such as the number of
items or lots
• Producing a label of dynamic length, rather than a fixed maximum number of records per
label
• Including only a subset of all the items of lots that are in a license plate, such as printing only
the top three lots by quantity
There are two types of label pre-processors that can address these types of requirements. The first
approach is for the system to produce only a single label that does not include all the data to be
included in the label, but rather includes a reference from which all the data can be gathered. Then the
pre-processor can directly query the database to get all the data. For instance, a label that lists all the
serials of a single item in an LPN is required. The Rules Engine can be used to select a special label
format whenever an LPN Content label for a serialized item is printed. That label would include the
LPN, item, lot, and revision, but no serial information (because serial data is not available to the LPN
Content label). The pre-processor would then directly query the serials and any other information to
include on the label.
The second, a pre-processor can rely on the multiple records of data, such as the multiple serials or
multiple items in an LPN, to be produced as single-record labels. The pre-processor can then
aggregate these multiple labels into a single label by modifying the XML, without querying the
database. For instance, suppose a single multi-record label is required that lists all the contents of a
license plate, no matter how many items or lots are in that license plate. While an LPN Summary
label format can be defined for multiple records, the maximum number of records to be included in
that label format must also be defined. Rather, the Rules Engine can be used to select a special label
format whenever an LPN Summary label is printed. That format should be a single-record format,
and the label pre-processor would then aggregate all the labels with the same format and license plate.
Note that most third-party label printing solutions do not support labels of dynamic length; they
typically require that the maximum number of fields on that label be defined in advance.
The database query approach may be slower because it requires that a database session be instantiated.
However, it avoids some timing issues that are introduced in converting single-record labels to multi-
record labels. Specifically, if the pre-processor runs in the middle of when a set of single-record
labels that are associated together are dropped to the XML directory, then the set will be split into two
separate labels, rather than being combined into one multi-record label.
The database query approach is similar to another example provided above. However, a label
aggregation approach is documented in the shell script below. Specifically, all labels that are of the
format identified by the variable LblFrmt will be merged into a single XML file in the destination
directory. The XML included in those files is unchanged, so that the labels ultimately produced by the
third-party software from this merged XML file should be identical to that produced by multiple
individual files. However, this script is demonstrative of how file merging can be used to build more
complex label files.
#!/bin/sh
#################################################
# This shell script has been created to
# demonstrate the extensibility of Oracle WMS
# labeling solution. It is not delivered as a
# standard Oracle product. Please feel free to
# edit or modify as needed.
#
# Author: Aditya Agarkar
#################################################
# This shell script scans the label output
# directory and merges multiple LPN summary
# label XML files for the same LPN into a
# single XML document. It assumes that, at the
# time that it runs, all the files that should
# be merged are present. It deletes the
# individual files that were merged, and creates
# a new merged XML file in the destination
# directory with the file name <LPN>.xml.
# Files that do not include the string identified
# by $LblFrmt are moved unchanged.
#################################################
# Enter source / destination directories here.
# - SrcDir must be the directory where Oracle
# drops the xml files, identified by the
# profile option WMS: Label Output Directory
# - DestDir must be the directory in which the
# third party label integration software
# expects to find the xml files.
#################################################
SrcDir=/home/dlwerthe/work/labels/test_in/
DestDir=/home/dlwerthe/work/labels/test_out/
#################################################
LblFrmt=LPNSUM
lastlpn=NULL
lpn=NULL
CtDate='date|cut -c1-3'
if test -f ${SrcDir}/*.xml
then
# Now look for files in Source Directory with the Prefix
for file in `ls -rt ${SrcDir}/*.xml`
do
lbl=`grep "labels _FORMAT =" $file|cut -f2 -d'"'|cut -f1 -d'.'`
if [ $lbl = $LblFrmt ]
then
# Check if XML file is for LPN Summary label
lpn=`grep "HLPN" $file| cut -f2 -d'>'|cut -f1 -d'<'`
# If this is the first LPN Summary file in the iteration...
if [ $lastlpn = NULL ]
then
lastlpn=$lpn
# Extract XML data without the </labels> tag
TotLines=`wc -l $file|cut -c1-9`
HeaderLines=`expr $TotLines - 1`
head -$HeaderLines $file>$DestDir/$lpn.xml
rm $file
else
# Is it a new LPN Summary Label file
if [ $lastlpn != $lpn ]
then
# Extract XML data without the </labels> tag
TotLines=`wc -l $file|cut -c1-9`
HeaderLines=`expr $TotLines - 1`
head -$HeaderLines $file>$DestDir/$lpn.xml
rm $file
echo "</labels>" >>$DestDir/$lastlpn.xml
lastlpn=$lpn
lpn=NULL
else
# XML file found for last LPN. Now consolidating with earlier file
# Extract XML data without the header and </labels> tag
TotLines=`wc -l $file|cut -c1-9`
RelevantLines=`expr $TotLines - 4`
HeaderLines=`expr $TotLines - 1`
head -$HeaderLines $file|tail -$RelevantLines>>$DestDir/$lpn.xml
rm $file
fi
fi
else
# This is not an LPN Summary Label. Close earlier label.
mv $file $DestDir
if [ $lastlpn != NULL ]
then
echo "</labels>" >>$DestDir/$lastlpn.xml
lpn=NULL
lastlpn=NULL
fi
fi
done
else
# No XML file with prefix found.....
if [ $lastlpn != NULL ]
then
echo "</labels>" >>$DestDir/$lastlpn.xml
lpn=NULL
lastlpn=NULL
fi
fi

Directory Monitoring
The label processing scripts above, when run, will go through all xml files in a given source directory,
modify the xml, and move the files to the destination directory. Label printing transactions will be
performed throughout the day so the label preprocessor should be set up to monitor the directory,
periodically checking for new files. There are two methods by which the script can be set to iterate
frequently.
First, the script can be set up as a cron job by adding a timing entry to the crontab file. While this
approach allows the operating system to manage the process, many operating systems do not support
scheduling a cron job to run any more frequently than every minute. The latency in label printing that
this will introduce is typically unacceptable in an interactive warehousing environment.
A more direct approach is to add a while loop surrounding the entire logic in the script, and to place a
sleep command at the end of the loop. A typical wait time may be five or ten seconds, but note that
this latency is introduced on top of the latency of the label printing software picking up the xml file
from the destination directory. The desire for a smaller latencies, and thus a smaller sleep time must
be balanced with the load the process may place on system resources. The first script above that
modifies the label quantity for certain label formats has been modified below to poll the source
directory every five seconds.
#!/bin/sh
#################################################
# This shell script has been created to
# demonstrate the extensibility of Oracle WMS
# labeling solution. It is not delivered as a
# standard Oracle product. Please feel free to
# edit or modify as needed.
#
# Author: David Wertheimer
#################################################
# This script iterates through each xml file in
# the source directory, replacing _QUANTITY="1"
# with _QUANTITY="2" if the file includes the
# text LG_MATERIAL and moving the new file to
# the destination directory. If the file does
# not contain the text LG_MATERIAL, it is moved
# to the destination directory unchanged.
#
# This script iterates in an infinite loop so
# that the source directory is continually
# monitored.
#################################################
# Enter source / destination directories here.
# - SrcDir must be the directory where Oracle
# drops the xml files, identified by the
# profile option WMS: Label Output Directory
# - DestDir must be the directory in which the
# third party label integration software
# expects to find the xml files.
# - WaitTime is the time, in seconds, that this
# script waits between polling the SrcDir for
# new files.
#################################################
SrcDir=/home/dlwerthe/work/labels/test_in/
DestDir=/home/dlwerthe/work/labels/test_out/
WaitTime=5
#################################################
# Start infinite loop here
while [ Date –eq Date]
do
# For each file in the source directory ending with *.xml
for file in ${SrcDir}*.xml
do
# The new file will have the same file name in the dest directory
ofile=$DestDir/`basename $file`
# If the text LG_MATERIAL is found in the label
if [ `grep '"LG_MATERIAL"' $file|wc -l` -eq 1 ]
then
# Copy the label to the destination, replacing the quantity
sed s/'_QUANTITY="1"'/'_QUANTITY="2"'/g < $file > $ofile
# Remove the original label file
rm $file
else
# Otherwise, move the label to the destination unchanged
mv $file $ofile
fi
done
echo "Waiting for files in $SrcDir...Press ctrl+c to abort."
sleep $WaitTime
done

Performance & Other Issues


The label preprocessing is primary a text processor, potentially integrated with database queries and
file management chores. A poorly written preprocessor can unnecessarily consume system resources,
and, if particularly slow, introducing additional latency beyond the two directory monitoring latencies.
Like any other customization effort, the pre-processor should be designed with performance in mind,
particularly because of the potentially large volume of labels that may be produced by the system.
The scripts above were written for clarity and accuracy, but often use inefficient processes. In
particular, the following issues should be considered when building a custom solution:
• Minimize access to the file system; avoid using temporary files, but rather write once to the
destination once the label is completely built in memory.
• Combine all database queries into a single session if possible, because instantiating a session
may be slow even if the individual queries to run are fast.
If there are many different customization requirements, each of which requires separate logic to
convert the original file to the required format, then a more modular approach should be taken, where
a parent script could cycle through all the XML files, immediately moving files that do not require
modifications to the destination directory, but kicking off background processes for the other files that
do require changes.
Also, any pre-processing scripts must be made robust, handling common error conditions gracefully,
or at least not error out. For instance, in the examples above, in order to calculate the set and cut, the
roll width is divided by the bobbin width. The bobbin width, whether populated in a flexfield or
queried directly from the database, may be null or populated as zero. This would cause a division by
zero, for which the shell script would ungracefully terminate, stopping all label printing, unless this
error was captured. At the very least, the pre-processor should continue to move other label files to
the destination directory. But the user must also be informed that the required bobbin labels cannot be
printed; a label with some error condition or text could also be printed out.

Custom Label Printing Call

Oracle WMS can automatically generate labels for several label types during about two-dozen
different business flows. Sometimes, however, a label is required during a business flow that does not
yet support label printing, or during a custom business flow that was built to support some specific
business requirement. Perhaps the existing label types and an XML pre-processor can be leveraged to
produce a label close to when the labels are required, such as the WIP Contents label being used in
examples above to produce the manufacturing labels with the required set and cut. However, there
just may not any printing close to what is required, and a different customization approach may then
be necessary.
The transaction or flow during which a label is required can be customized to call the label printing
code directly. For instance, none of the desktop material receipt transactions print a label, yet desktop
receipts may be used commonly and, for certain business reasons, it may not be possible to use the
mobile forms to either perform the transaction or to perform a manual print request afterwards. Or a
shipping content label, ordinarily available when an LPN is either loaded or dropped, or during the
ship confirmation flow, may be required as soon as the task is initially presented to the user. This may
be because the users get their labels from a centrally located label printer and by the time the user
loads (or drops) the task, the user may be far from that printer.
For these requirements, the transaction or flow can call the same APIs used by label printing. The
following API can be used when label printing is called from Java:
PROCEDURE PRINT_LABEL_MANUAL_WRAP
(
x_return_status OUT VARCHAR2
, x_msg_count OUT NUMBER
, x_msg_data OUT VARCHAR2
, x_label_status OUT VARCHAR2
, p_business_flow_code IN NUMBER
, p_label_type_id IN NUMBER
, p_organization_id IN NUMBER
, p_inventory_item_id IN NUMBER
, p_revision IN VARCHAR2
, p_lot_number IN VARCHAR2
, p_fm_serial_number IN VARCHAR2
, p_to_serial_number IN VARCHAR2
, p_lpn_id IN NUMBER
, p_subinventory_code IN VARCHAR2
, p_locator_id IN NUMBER
, p_delivery_id IN NUMBER
, p_quantity IN NUMBER
, p_uom IN VARCHAR2
, p_no_of_copies IN NUMBER
, p_fm_schedule_number IN VARCHAR2
, p_to_schedule_number IN VARCHAR2
, p_format_id IN NUMBER
, p_printer_name IN VARCHAR2
)

The proper label type can be selected from the lookup codes defined in MFG_LOOKUPS:
select lookup_code, meaning from mfg_lookups where lookup_type = 'WMS_LABEL_TYPE'

The business flow code should be passed in as null for a manual label request, while the label format
and printer name can either be passed in explicitly, or left for the Rules Engine and printer
assignments to determine. Similarly, not all of the parameters are necessary for each label type. For
instance, the Material label has no references to job, schedule, or serial number, so when a Material
label type is being printed, those parameters should be passed as null. To see exactly which
parameters are required for each label type, observe the behavior of the Manual Print page on the
mobile. For instance, a Material label is driven by the item, and as applicable, revision, and lot
numbers, as well as the quantity and UOM of the item, while the LPN Summary label type requires
only a license plate.
If label printing is called from PL/SQL, the following call should be used instead:
PROCEDURE PRINT_LABEL
(
x_return_status OUT VARCHAR2
, x_msg_count OUT NUMBER
, x_msg_data OUT VARCHAR2
, x_label_status OUT VARCHAR2
, p_api_version IN NUMBER
, p_init_msg_list IN VARCHAR2
, p_commit IN VARCHAR2
, p_print_mode IN NUMBER
, p_business_flow_code IN NUMBER
, p_transaction_id IN transaction_id_rec_type
, p_input_param_rec IN input_parameter_rec_type
, p_label_type_id IN NUMBER
, p_no_of_copies IN NUMBER
, p_transaction_identifier IN NUMBER
, p_format_id IN NUMBER
, p_printer_name IN VARCHAR2
)

PRINT_LABEL_MANUAL_WRAP is a wrapper for PRINT_LABEL that avoids the use of


structures; otherwise the calls are identical. Both can be found in INVLABPB.pls.
As this type of customization requires directly modifying the code to change the process by which
labels are called, it carries the standard risks that patches may overwrite the customizations, and future
releases may require re-engineering of the customization in that the specification of the manual label
print API or other APIs may change.

Summary
Oracle WMS provides a flexible way to print any number of different labels during almost every
transaction or event supported on the mobile device. The flexibility of the label printing solution,
combined with the flexibility of the WMS Rules Engine and the third-party label printing software,
should remove many of the needs to customize label printing.
However, if the business requirements cannot be modeled by standard functionality, and cannot be
altered, then three approaches to customization are available that should make label printing much
more flexible. Custom triggers can populate flexfields that can be easily included on the labels, so
that additional data can be made available for the labels. An XML pre-processor can directly modify
the XML produced by WMS prior to the third-party label software picking it up, changing the
structure of the label, adding additional data from direct database queries, or just performing basic
manipulations not available in the third-party software. Finally, additional calls to the label printing
APIs can be made so that labels are printed during flows that do not already print labels.
As Oracle WMS expands the features available as standard functionality, the need for many of these
may disappear, but there may always be some industry-specific or company-specific requirements that
WMS just can not meet out of the box. These three approaches to requirements allow any label to be
printed at any time, including any data, and combined with the flexibility offered by both Oracle and
the third-party label software, should be able to meet all requirements.
October 2002
Author: David Wertheimer
Copyright © Oracle Corporation 2002
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.

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 2002


All Rights Reserved

You might also like