Bye-bye work report, welcome wave labels!

Bye-bye work report, welcome wave labels!

One of the common customizations of the Dynamics 365 Warehouse management module was the automatic printing of the work report [for the sales order picking work]. If the number of shipments exceeds a hundred per day, the electronic work list (Menu item type = Display open work list) on the Warehouse mobile device becomes unmanageable, and the distribution of the daily picking work amongst the warehouse workers requires printing and sorting of some carbon documents. This used to be the Work report in the Warehouse management > Work > All work list. However, it is better printed interactively out of the browser UI i.e., the supervisor requires a PC with a mouse, and the printing can hardly be automated / integrated with the other wave processing steps.

The latest Wave label printing – Supply Chain Management | Dynamics 365 | Microsoft Docs feature is the remedy;
In the Containerization scenario, the Wave label type is assigned to the respective level in the Unit sequence group:

Yet the Wave label printing can not only produce box labels after the system-driven containerization, but also simply print the picking work i.e., it will take the Work headers and Lines as a data source and send them to the label printer(s)!

Wave label printing setup

Activate the wave label printing feature on the Feature management screen. Add a new Warehouse management > Setup > Document routing > Wave label type.

The Wave label layout is by far more complex than the classic put-away routing layout. It consists of a Header and a Footer static ZPL code, and a dynamic Body ZPL part. With 0..N bodies per label, the Wave label feature may render complex business documents of a variable height, such as a Bill of lading.

The below sample layout prints just one label = header + body + footer for every Pick work line (see Wave label row settings, Rows per page = 1). Create a Wave label row settings / Row ID = XXX first, then use the proprietary <Row name =”XXX”>… </Row> closed tag in the Body section:

Header
^XA
^SZ2^JMA
^MCY^PMN
^PW810
~JSN
^JZY
^LH0,0^LRN

Body
<Row name="WorkLine">
^FT21,37
^CI0
^A0N,28,38^FDPicking label ¸ Eugen Glasow^FS
^FO17,54
^BY3^BCN,102,N,N^FD>:$WHSWorkLine.WorkId$^FS
^FT135,182
^A0N,28,38^FD$WHSWorkLine.WorkId$^FS
^FT21,276
^A0N,28,38^FDSales order:^FS
^FT214,276
^A0N,28,38^FD$WHSWorkLine.OrderNum$^FS
^FT52,236
^A0N,28,38^FDShipment:^FS
^FT214,236
^A0N,28,38^FD$WHSWorkTable.ShipmentId$^FS
^FT541,50
^A0N,34,46^FDPacking^FS
^FT541,85
^A0N,34,46^FDLocation:^FS
^FT589,133
^A0N,34,46^FD$WHSWorkLine.WMSLocationId$^FS
^FO640,235
^BQN,2,6^FN1^FS
^FT571,390
^A0N,28,31^FN2^FS
^FT651,216
^A0N,28,38^FDPart no:^FS
^FT146,316
^A0N,28,38^FDQty:^FS
^FT214,316
^A0N,28,38^FD$WHSWorkLine.QtyWork$^FS
^FT110,356
^A0N,28,38^FDBatch:^FS
^FO214,331
^GB266,30,30^FS
^FT214,357
^A0N,28,53^FR^FD$WHSWorkLine.FEFOBatchId$^FS
^XZ
^XA
^XFR:SSFMT000.ZPL^FS
^FN1^FDLA,$WHSWorkLine.ItemId$^FS
^FN2^FD$WHSWorkLine.ItemId$^FS
</Row>

Footer
^PQ1,0,1,Y
^XZ

In the Wave label template, the labels may be sent to different label printers depending on the picking Zone, for instance. Moreover, a separator – a zone Break label – may be inserted into the endless stream of picking labels for the tearing at the right place. This requires a sorting (see Edit query) by the Zone field and a Group by + Print break label option under Wave label template group. From my experience, more than one sorting / grouping level does not work.

Work label printing: test run

The above layout may be used not only for managing the picking work, but also for labelling the picked items for the end customer with the sales order / shipment / transport package ID:

To test the labels, create a wave step code “Label Printing”, and add the waveLabelPrinting method to the Wave template right after the work creation step. Release some test sales orders to the warehouse, then Process the outbound wave.
A warning “There is no unit for the … wave label type on the … unit sequence group. Wave labels are not created for the … item” may be shown, but it may be ignored. A stream of labels should come out of the printer, one per picking work line for every work header created.

WHS Label copies, Custom work, display methods on labels

WHS Label copies, Custom work, display methods on labels

Todays exercise is seemingly simple: print a voluntary number of warehouse label copies where the standard Dynamics 365 SCM only prints one. The ingredients are quite exquisite and variegated:

^PQ

Let’s start with a proof of concept: print as many labels as there are items. Assuming there are 3 items on the license plate (pallet), let’s print the same label 3 times. This sounds simple, yet you need the latest and the coolest feature Enhanced license plate label layouts. With that feature you can finally carve a substring from Dynamics data, but also format numbers and dates. This is exactly what we need.

In Warehouse management > Setup > Document routing > Document routing layouts, every Zebra label template ends with something like
^PQ1,0,1,Y
which is the instruction to the label printer how many copies to print. Now replace this line with
^PQ$Qty:0$,0,1,Y
The quantity as a real number is truncated to an integer on the label, and the ZPL printer makes as many copies as there were pieces on the pallet.

Display method

A real game changer is now the ability to parse a display method on the WMSLicensePlateLabel table. Let Dynamics calculate the number of copies on the fly, leveraging the PackingQty factor which is the number of pieces in the topmost unit of the Unit sequence group. Assuming the unit sequence group is PCS-BOX i.e. pieces in boxes and if the nominal quantity per box is 20, for a license plate with 100 items on it I would like to have 5 copies of the label.

Extend the WMSLicensePlateLabel as follows
[ExtensionOf(tableStr(WHSLicensePlateLabel))]
final class WHSLicensePlateLabel_Extension
{
display Num noOfCopiesSimple()
{
return int2Str(this.PackingQty > 1 ? any2Int(roundUp(this.Qty / this.PackingQty,1)) : 1);
}
}

and embed it into the ZPL code like this:
^PQ$noOfCopiesSimple()$,0,1,Y

Now the number of copies is dynamic, configurable and obeys the master data settings.

Custom work

The high-end solution is to let the user override and decide how many copies to print. In order to do that, before the Print line in the Work template we need an extra screen of the Custom work type:
Custom work type

This brings the following prompt on the mobile device

You may also want to explore possibilities of simple validations and post-processing of the data captured on the Custom work screen:
Custom method tutorial.

The number of copies entered by the user is then interpreted by a more sophisticated display method:
display Num noOfCopies()
{
int noOfCopies;
WHSWorkLineCustom workLineCustom;
WHSWorkLine workLine;
select firstonly Data from workLineCustom
exists join workLine
where workLine.WorkId == this.WorkId
&& workLine.WorkType == WHSWorkType::Custom
&& workLineCustom.WorkId == workLine.WorkId
&& workLineCustom.LineNum == workLine.LineNum;
if (workLineCustom.Data)
{
noOfCopies = str2Int(workLineCustom.Data);
}
if (! noOfCopies)
{
noOfCopies = this.PackingQty > 1 ? any2Int(roundUp(this.Qty / this.PackingQty,1)) : 1;
}
return int2Str(noOfCopies);
}

Enjoy!

Towards the deconsolidation in Dynamics Warehouse Management

Towards the deconsolidation in Dynamics Warehouse Management

The deconsolidation (opening of a complex packaging, quality control, taking small packages out of the larger packages announced by the supplier of the goods via ASN) seems to be a well-established process in SAP EWM, yet the implementation in Dynamics for SCM, its WHS module may turn cumbersome. Below is the workflow one may configure in Dynamics WHS out of the box:

Deconsolidation workflow

It all begins with an Advance Shipping Notice transmission and import. The invaluable – and only available – source on this topic is located here: Processing of inbound ASNs in Warehouse Management in AX ‘7’ (kashperuk.blogspot.com). The ASN creates an inbound load and a packing structure for a Purchase Order in Dynamics. I identified 2 distinct scenarios:

  • Multi-SKU: The packing structure contains multiple items in one single box (or on one pallet). Here one needs to understand that the Import project in Dynamics Data management must still be “pre-conditioned” with an XML file containing nested cases (boxes) and all 6 entities in the composite entity “Inbound ASN” even though the real message will not be using either the WHSInboundLoadPackingStructureCaseEntity (representing the nested license plates i.e. packing structure cases) nor the WHSInboundLoadPackingStructureCaseLineV2Entity (the one with the items in the packing case). My file for the pre-conditioning is here: InboundASN_ASNEntityConditioning, while the real message can be stripped down to 4 entities
    the load Id
    … the purchase order(s) in that load
    …… the parent license plate(s)
    ……… the content of the license plate
  • Multi-case: the ASN contains a packing structure (max. 1 level of depth) where the boxes (packing cases) are on the Parent License plate (i.e. pallet or master box), and the multiple items are in their own cases (boxes). An example is here: InboundASN_NestedLPCase. Let’s state one thing straight: the process does not work in this scenario. Let’s explore, why.

Nested LP (multi case) scenario

Once the ASN has been imported, navigate to Warehouse management > Loads > Open loads, then open Ship and receive / Packing structure:

The cases (aka nested license plates) 00708581a and 00708581b are on the parent license plate 00708581 and contain the items. Use the Mobile menu item License plate receiving to process this ASN. It displays the list of the items and let the parent and the nested license plates emerge at the default receipt location (here: DOOR). The system registers the parent and the nested LPs all right, but the stock of the items is on the parent LP only!

This fundamental flaw in Dynamics is well documented here: License plate receiving via the Warehouse Management mobile app and therefore becomes a ‘feature’, not a ‘bug’ 😉 They further suggest using a Pack to nested license plates indirect menu item to distribute the stock over the nested LPs in accordance with the ASN, but here is how it is going to end:
Pack to nested license plates

This action culminates in an “insufficient on-hand” error, because the moment you receive the parent LP, it generates the put-away work and reserves the whole freshly received quantity for the same. The stock cannot be moved (because this is what the Pack to nested license plates really does: creates a series of movements between the parent and the nested licence plates).

The typical approach is to let the put-away work be omitted with a Work policy, or be automatically performed for the stock to stay at some logical staging location right after the receipt. The split nested LPs are then distributed into the main storage with a Movement by template menu item. However, a movement by template does not support either the Disposition codes or the Quality management (Quality management for warehouse processes – Supply Chain Management), because both the QC methods are only allowed for purchase orders and production orders, not the movements. This essentially rules out the standard WHS quality control.

The only viable solution is to elevate the cases to parent LPs in the ASN interface, i.e. to convert nested cases to multiple “parents” of their own. This effectively reduces the nested-LP scenario to a multi-parent, multi-SKU one:

Multi-SKU scenario

The list of the Cases in the Packing structure is empty now; instead, one or many parent license plates contain one or many items each:

Now, the secret of the proper work processing, deconsolidation and the proper location determination is the staged Work template for the purchase order receiving process:
Location DOOR → DECO → Final BIN or bulk location

The DOOR location is considered the staging area before the deconsolidation, while the DECO location (injected by the Directive code = Stage in the work template / location directive) is the staging area after the deconsolidation where the put-away work is sorted and clustered for further processing:
Purchase order work template
The process needs 3 mobile menu items: License plate receiving – Work (one Work class ID) – Work (another class ID).

The Print work type here substitutes the Print checkbox on the menu item, because the latter is printed earlier when the parent LP is at the DOOR while it is considered a Multi-SKU license plate: it is going to be printed only once and the item number and the location are going to be empty. Also note the Stop work break after the deconsolidation part (lines 1-4) to interrupt the flow at the DECO staging location and transfer the duties from one warehouse team to another.

The second piece of the puzzle is the Work header break by the Item number: it will create as many work headers as there are items, all for the same parent LP, with a unique final Put location each. This location is nicely printed on the label, along with the Item ID, i.e. we have successfully reduced a Multi-SKU case to a single-SKU one to locate a unique bin by item.

At the deconsolidation station, the same parent LP is scanned over and over again and it randomly directs to the next open purchase work = item to be taken out from the parent LP. A quality control is nicely tied in (however, the ASN quantity as a whole may be either accepted or rejected; a single damaged piece may only be split in a separate movement process at a QC location if fully rejected first):
Deconsolidation process

The last piece of the puzzle is the Generate license plate option at the menu item for the purchase work processing:

It replaces the ambiguous Parent LP number with a fresh unambiguous LP number (see the Confirm target license plate step above). The same is used by the “put-away people” to initiate the final movement into the destination bin / bulk location (lines 5-6 in the Work template):
PO put-away process

Bingo!

The last trick may be a batch job (Warehouse management > Periodic tasks > Change inventory status) updating the Inventory status from Blocked to Available in every bin, bulk, floor location every 2 minutes. The reason is a potentially early reservation of the goods in the receiving / staging locations while the quality inspection might not yet have taken place. The sales order location directives consider the regular bin/bulk/floor locations only, and the reservation in the receiving area results in an empty Pick location in the outbound work. Use the setting Warehouse management > Setup > Inventory > Default item status to enforce the Blocked, non-reserveable inventory status upon all purchase orders. With N items from M suppliers this requires N*M lines in that form, unfortunately 🙁