Cover V09, I07
Figure 1
Listing 1


Integrating Barcodes

Doug Rusk

My company offers after market solutions for the computer industry. We specialize in parts sourcing, procurement and stocking, inventory management, systems sales, returned goods management, etc. We currently process over 4,000 shipments a day from four facilities, so when an opportunity to save shipping time is suggested, we're always interested. One area of continuous improvement is in the use of barcodes throughout the repair process in all facilities. By placing barcodes for sales order number, pick number, and customer site code on pick tickets, a savings of 5 - 10 seconds per shipment can be realized. This change, coupled with the loading of specific customer site codes into our manifesting system, could reduce handling time by an additional 10 seconds per package -- an improvement of 25% when 80 seconds is the average time it takes to process an order.

This article covers the development of an integrated system, which allows seamless introduction of barcodes into operational documents. These documents (pick tickets) are used to control the selection and shipment of inventory for customers from our facilities. Of interest to systems administrators is the speed with which this system was developed, and the ease of use for the end users; there were no procedural changes required to put this system into production.

The system this particular improvement would impact is Dispatch-1 (D1) from Astea; a Progress-based manufacturing and inventory control system running on an IBM AIX/RISC 6000 server. We use D1 to process both standard sales orders and customer system repairs from the “Depot” module (RA records). Both of these subsystems use picking documents to ship product to a customer, so whatever solution was chosen would have to work seamlessly for each module.

D1 is quite flexible when it comes to adding or modifying standard processes. The application supplies “user exits” at various points to allow customer-defined programs to execute at specific places within the application. These can be as simple as requesting more data from an end user or running complete external modules.

During the research phase of this project, my first thought was to use the previously mentioned “user exits” as an interrupt to the standard pick printing process. If the users then ran the pick program, but redirected the “normal” output stream to a “null” device, the user exit program I developed could be used to recreate the pick document with barcodes encoded within it and then route the picks to the standard printer. After examining the placement of the user exits, I determined that one's not in the right place. I contacted Astea to look into placing a user exit where needed, but decided this option required too much development even with the exit exactly where I needed it.

My second idea was to rewrite the entire pick-printing module by acquiring the source code from Astea. This appealed to me because it would have given me the most flexibility in terms of user exit control, barcode placement on the pick-ticket, and more control over performance; elements that could offset the cost of such a major development effort. As with the idea above, I determined this would take too long to produce since Operations had given this project highest priority.

My final idea was to work downstream from the application and modify the print file generated from the picking process before it passed to the UNIX queuing system. Since a print job in UNIX is just a straight text file, it should be easy to take control of these files and manipulate them. The advantage of this approach was that it avoided modifying the application, and it gave a lot of flexibility in dealing with picks generated from different modules in the D1 system (sales and depot repair). If all documents that required barcodes could pass through a program at the operating system level before printing, this would achieve the desired result, and it would be very efficient.

I went to the Web and entered the search string “UNIX BARCODES”, and the site for Unibar came up immediately:

Unibar, Inc. provides a variety of barcoding products for UNIX, Windows 95/98/NT, and Linux environments. Our barcoding solutions include program modules that easily integrate with existing customer applications, databases and vertical programs such as ORACLE, PROGRESS, Informix, BAAN, SAP and others.

The program “ubz” interprets textural start and stop characters to generate graphics in place of text. This program works with a configuration file, which lets you set such things as barcode size, density, text options etc. This program takes as input a text stream and allows you to define a start and end character, which it will use to turn on and off the bar-coding generation. The default characters are '~' for “start barcode” and “ “ (blank) for “end barcode”.

I downloaded the software from the Web site and was generating barcodes on my test machine within 5 minutes of receiving a temporary software license key from Unibar. Setup included unzipping the file into an execution directory, and creating a “UNIBAR” environment variable set to the location of the software license key.

Initial testing was very positive; I simply “echoed” a text string with the appropriate start character to the Unibar program “barz” and then piped the output to the queuing system specifying an HP LaserJet printer:

echo "~123456789" | /usr/bin/ubz -CFGubz.cfg  | qprt -Pgvmis1
The printer immediately spit out a single page with a barcode on the first line. I checked to confirm that the barcode was the right protocol (3 of 9) and moved onto the next step.

I wrote a shell script, which would take a text stream as input, run it through the “ubz” program, and pass it onto the appropriate laser printer:

/usr/bin/ubz -cf./usr/bin/ubz.cfg | qprt -Pgvwhse1
I tested this by piping the output from the cat command to this script, which printed the file just as I expected. There was no discernable delay and “non barcoded” files processed this way printed out normally:

cat testfile | /usr/bin/
Next I set up a “printer device” on D1, which called the script instead of the standard qprt process usually used by D1/AIX (see gvwh1ubz below.) This would allow an end user to select a “barcode ready” device instead of their usual output device for printing pick tickets. Eventually, I simply converted the standard printed device on D1 to use the barz script instead of qprt, (see Figure 1.)

I came to this conclusion after realizing that passing “standard” print jobs through the filter had no negative impact on the printing process. If there were no fields flagged for barcodes, the text simply passed onto the printer queue with no delay.

Once these OS-level issues were resolved, I had to develop a way to place text strings with the correct start and end characters within the pick ticket output stream generated by D1. One attribute of D1 is that sales order and depot repair “external comments” (remark-file records) are displayed on pick tickets under the header data and above the item detail. This would be good placement for the barcodes, as they would appear on every page of the pick, allowing barcoded multi-page picks to be distributed across the warehouse. These comments are usually generated by sales support staff to inform the shipping department when special handling has to occur.

I analyzed the remark-file records entered for previous sales and determined which fields I would have to populate within the remark-file table to create comments that could be converted into barcodes (comments proceeded with a “~”). I tested this code by creating a remark-file record from the Progress editor, which had as the “data field” the sales order number preceded by a tilde: “~CA03100001”. I checked the validity of this record by referencing it through the standard “order update” screens of D1. I found the comment created and confirmed that I could update or delete it as desired.

I printed a pick ticket for this order through the standard queuing system to check the placement of the comment on the pick. Just as I expected, “~CA03100001” appeared on the main page of the pick above the line items for the order. I then reprinted this pick through the gvwh1ubz printer set up on D1 and saw the order number printed out as a barcode, exactly where I needed it. All that remained was to figure out how to make the application generate these comments automatically.

Progress supports “database triggers”, a programming device that allows you to execute a program when a specific record-level activity takes place. Options include create, delete, or write triggers. Since the picking process generates and updates “pick-file” records when picks are printed or reprinted, database triggers could be used to generate remark-file records for sales orders or RA's as the pick-file records are processed. To determine which programs were modifying picks during the pick printing process, I wrote a “write database” trigger program that displayed the current program name being executed each time the pick-file table was written to (i.e., each time a pick-file record was updated):

By running this “trace program” I found that pick-file records were updated three times during the standard pick print process from the following programs:

Now I knew that I had the means to initiate the creation of remark-file records for specific sales or RA whenever picks were printed. I created a WRITE-TRIGGER program on the test system, which created a remark-file record containing the sales order number preceded by a “~”, and ran a pick for a sales order. I then checked the remark-file table and found three identical records created. This was great except that I did not need three remarks with the sales order, only one. So I changed my program to execute only when the function “PROGRAM-NAME(2)” returned the same value as the second program in the pick execution stream (see trace above.) “PROGRAM-NAME(2)” returns the name of the last calling program in the stack, not the current “called” program that would be referenced through “PROGRAM-NAME(1)”. Once this addition was in place, the program executed only once, resulting in the single remark record.

Now all the pieces were in place. Since we needed three barcodes imbedded in the pick (order number, pick number, and site-code), I modified the code to run three times within a loop and work with conditional assignments based on the counter (see Listing 1).

Initial testing went very well; the only change was to check for a remark-file record containing the string “PICK NUMBER” and, if found, reset the data field to the pick currently running. Since an order can have multiple picks tied to it, this change updated the pick number to reflect the current pick being printed.

The “new” pick form was tested with several orders before the system was put into production. One minor modification was the offset of the sales order barcode with the other two because the proximity of the three barcodes in a single column made it too easy to read the wrong field. Another request was to program into the scanner an automatic “F1” key after scanning the order number at one particular station. F1 is used by D1 to process the current field of data, so this change allowed an end user to use the scanner without then having to manually type F1 on the keyboard.

The new picks are working exactly as planned. Total cost for this project came to $590.00 for the UNIBAR software and about 8 hours of programming and testing time for me, which translates into significant annual savings. This was an excellent exercise for me in systems integration, and the combination of Progress functionality, UNIX shell scripting, and Unibar software made the development of this low-cost process easy.

About the Author

Doug Rusk is Director of IT for ExpressPoint Technology Services Inc. in Golden Valley, Minnesota. He specializes in manufacturing solutions and has been developing in Progress and the UNIX environment for more than 10 years. He can be reached at: