Add Validated Offline Scanning to Warehouse Workflows in Dynamics 365

Fast Validation

The Fast Validation page pattern has been added as a private preview in the 10.0.12 release.  This works in a similar way to the multi-asset scanning page pattern that was discussed here (link), however this new pattern allows for client-side (i.e. offline) validation against a user-defined list of values.  This can be very useful for building fast scanning applications that need to ensure accuracy of the data scanned.  This article will show you how to implement a basic fast validation pattern in the warehouse mobile app.

Demo Flow

As of 10.0.12 this feature has only been included in two flows in the core product – License Plate Consolidation and Catch weight tag scanning.  It is also possible to see the new functionality in the demo mode within the latest warehouse mobile app.  In the latest version (1.8 as of this writing) the demo menu looks like this:

The LP Consolidation menu item will give you a good feel for what this Fast Validation framework can provide.  Note that the actual LP Consolidation menu item within the product can support this framework if the correct flighting and feature flags are configured as detailed below.

The first screen will allow you to specify the Target LP (any value here will be fine):

The next screen shows the new UI for the Fast validation feature:

Scanning values here will be done offline with no communication to the server.  The system has downloaded the list of possible license plates to the mobile device and these are now used to validate the user data.

For example – entering “LPx” will show this error telling the user that “LPx” was not a valid License Plate to use for the consolidation:

However, entering “lp1” produces the following screen – indicating this is a valid license plate available for consolidation:

You can see the full list of valid license plates as well as what has been scanned already by clicking the menu icon in the lower left corner – this shows a new screen with the scanned and validated values (called “Merged” in this example) and the list of total possible license plates (called “Available”).

Finally – going back to the main screen you can see there is a check mark icon in the lower right.  This will allow you to submit the final list to the server for processing.  We will talk later about the API used to send the list of scanned values to the server-side X++ processing logic – it works very similar to the multi-asset scanning API.

Setup

As of 10.0.12 this feature can be used for custom development using the patterns discussed below.  If you want to see the flow(s) available in the core product, then you will need to enable the following flight as well as enable a feature within Feature Management.  As discussed above the two flows that have been enabled in 10.0.12 are LP Consolidation and Catch Weight Tag scanning.

Flight Name: WHSRFFastValidationFeature

Once the above flight has been added to the development environment the following feature will need to be enabled:

In addition, the latest warehouse mobile app build will need to be utilized.  The required UI components are included in the 1.8 version of the app, which can be found in the Windows Store and Google Play store.

Sample Process

The provided solution works in tandem with the previous multi-asset scanning demo.  Imagine a scenario where the first station in the warehouse scans all the possible assets for a container.  Then the container goes through a round of packing where specific items are placed into the box – but we can limit the possible items to the ones previously scanned. If we want these scans to be as fast as possible, we can utilize the new offline scanning mode with the validation to ensure we only allow input from the list of possible assets.

The workflow in the demo looks like this:

Multi-Asset Scanning

  1. User logs into the multi-asset menu item
  2. Scans a Container ID
  3. Scans a set of Assets that are associated with the container.
    1. These are stored in the database associated with this specific ContainerID
    2. These scans are all performed offline using the multi-asset scanning mode previously released and documented

Fast Validation Asset Scanning

  1. Another user logs into the fast validation menu item
  2. Scans the same Container ID
  3. The super-set of possible Assets are retrieved from the database and used as the validation list in the Fast Validation UI
  4. The user can then scan Assets to store against this container – but the user input is restricted to the possible Assets associated in the previous step.

Multi-Asset Scanning

The first steps are done in the multi-asset scanning menu item described in the previous post here.  In this flow you can scan a container id and then scan any number of assets to associate with the container.  These will be saved into a custom WHSAsset table mapping the ContainerID to the new Assets.

Scanned Assets using the multi-scan UI:

These assets are stored into a custom table (WHSAsset) with a simple linking between the Container and Asset:

Fast Validation Flow

Now that the full list of assets have been scanned we can launch the Fast Validation scanning Menu Item.  This will again ask us to scan the Container ID – however it will now utilize the previously saved data to build the validation list.

In the sample provided – the initial Fast Validation screen is displayed like this:

The string values “Scan Assets” and “Assets to Scan” come from the setup parameters defined in the code as described below. Scanning a value that passes validation (i.e. it is within the list) will display the success scanning message like this:

Scanning an incorrect value (i.e. a value not in the valid list) will display the error message:

And scanning a duplicate value (i.e. if we scan 111 again) the duplicate message will be displayed:

Clicking the menu button will display a new screen with the list of already scanned values and possible valid data.  The titles of these tabs are also defined in the code detailed below.

For the demo flow let’s say we enter two more valid assets to pack into the container – “222” and “333.”  Then when we finalize the flow the mobile device will display the success message and the database should be updated to reflect the newly validated list of assets.

Again – remember that this is simply a demo flow to highlight how the offline scanning UI can be utilized in custom flows.  It does not reflect a realistic business scenario without some additional work.

API

Adding the Fast Validation page pattern to a page involves using the new class WHSFastValidationControlsBuildParameters.  When you construct one of these objects you can specify several parameters:

Input NameName of the input control to use for the stored data.  This is the “key” used to store the input data in the pass object.
Input LabelLabel to display to the user on the fast validation screen.
Input TypeThe EDT of the data to be scanned by the user.
DataA container with the possible values the user can scan against.
Fail MessageMessage to display to the user when a value is scanned that is not in the valid list.
Success MessageMessage to display to the user when a value is successfully scanned and validated against the data list.
Duplicate MessageMessage to display to the user when a value is scanned that has already been successfully scanned.
Title – Scanned ListThe text to display in the UI for the list of values that have been successfully scanned.
Title – To Be Scanned ListThe text to display in the UI for the list of possible values that can be scanned.
Sound on SuccessBoolean value that controls if a successful scan will trigger an audible feedback to the user.
Sound on FailureBoolean value that controls if a failed scan will trigger an audible feedback to the user.

In the sample app provided the above settings are all configured through the following code.  Note that this API assumes you are using the ProcessGuide framework, as a new method has been added to the ProcessGuidePage class.

protected void addDataControls(ProcessGuidePage _page)
    {
        WhsrfPassthrough pass = controller.parmSessionState().parmPass();
        WHSContainerId containerId = pass.lookupStr(ProcessGuideDataTypeNames::ContainerId);

        _page.addLabel(ProcessGuideDataTypeNames::ValidationScanLabel, 'Scan Assets', extendedTypeNum(WHSRFLabel));
        _page.addTextBox(ProcessGuideDataTypeNames::ContainerId, 'Container Id', extendedTypeNum(WHSContainerId), false, containerId);
        
        WHSFastValidationControlsBuildParameters  fastValidationControlsBuildParameters  = WHSFastValidationControlsBuildParameters::newFromParams(ProcessGuideDataTypeNames::ValidatedAssetList,
         'Assets to scan',
         extendedTypeNum(AssetIdList),
         this.getAssetIdList(containerId), 
         "@WAX:FastValidationMsgScanFailPick",
         "@WAX:FastValidationMsgScanSuccessPick",
         "@WAX:FastValidationMsgScanDuplicatedPick",
         "@WAX:FastValidationTitleListMergedLPs",
         "@WAX:FastValidationTitleListAvailableLPs",
         NoYes::Yes,
         NoYes::No);

        fastValidationControlsBuildParameters.scanTitle = "Scan Assets";
        _page.addFastValidationControls(fastValidationControlsBuildParameters);
    }

Processing Data

The mobile app will allow the user to stay on the scanning page and continue scanning data – it will not return to the server until the user taps the checkbox icon.  This will then submit the final list of values that have been scanned by the user for processing by the server-side code.  The values will be accessible to the server-side code in the pass object – under the key used for the “Input Name” value.  This will be a pipe separated list of values (there is an existing constant that defines the separator – ProcessGuidePageConstants::FastValidationListSeparator).

In the same project the following code is used to parse the incoming values – the highlighted line is the area where the scanned values are extracted from the pass object.

protected void doExecute()
    {
        WhsrfPassthrough pass = controller.parmSessionState().parmPass();
        WHSContainerId containerId = pass.lookupStr(ProcessGuideDataTypeNames::ContainerId);
        WHSAsset AssetTable;

        delete_from AssetTable
            where AssetTable.ContainerId == containerId;

        container selectedAssetsIds = str2con(pass.lookupStr(ProcessGuideDataTypeNames::ValidatedAssetList), ProcessGuidePageConstants::FastValidationListSeparator);

        int	len = conLen(selectedAssetsIds);

        for (int i = 1; i <= len; i++)
        {
            str AssetId = conPeek(selectedAssetsIds, i);
            WHSAsset newAsset;
            newAsset.ContainerId = containerId;
            newAsset.WHSAssetId = AssetId;
            newAsset.insert();
        }

        pass.remove(ProcessGuideDataTypeNames::ValidatedAssetList);
        pass.remove(ProcessGuideDataTypeNames::ContainerId);

        this.addProcessCompleteMessage();

        super();
            
    }

Conclusion

This article has explained the new Fast Validation scanning feature and how to enable it in a custom flow. You can download the complete solution here – hopefully it helps you to utilize this new capability we have added to the Dynamics product. As always please understand this code is intended for demonstration only and should not be used in a production system without extensive testing.