Minimum Requirements

  • Mobile WMS 3.12 for Dynamics AX2012 or Dynamics 365 SCM/FO

Description

Write a new class that adds the possibility to validate values entered on the device during receipt processSome of the static/planned processes of the Mobile WMS may in some cases need validation to ensure the data entered is valid. This is done by setting up an online call to the backend, that has the values entered by the user on the mobile device.


For this example we will make a validation of the Location entered on the device and the quantity entered during reception.


On the device, find the configuration file, and navigate to the service relevant to the process you need to enhance with validation, and change it like this:

<service id="Receive" orderType="Receive" type="Order" workflowId="Receive" useOrderLocking="true">
    <requests>
      <getOrders>GetReceiveOrders</getOrders>
      <getOrderLines>GetReceiveOrderLines</getOrderLines>
      <postOrder>PostReceiveOrder</postOrder>
    </requests>
     <validation>
      <quantityValidation online="true" documentName="ValidateQuantityReceive" includeCollectedValues="true" />
      <toBinValidation online="true" documentName="ValidateLocationReceive" includeCollectedValues="true" />
    </validation>
  </service>



Be aware that from Mobile WMS version 3.14 and onwards, the above process of changing the configuration is done in the "Workflows" screen, and changing the configuration file is from this version no longer necessary.


Once you have modified the configuration, it is time to add code to handle the validation.


Make a new class that extends MobDocumentHandler. It could look like this:

Class declaration
class MobDocReceiveValidation extends MobDocumentHandler
{
    public MobDocumentHandlerDescription description()
    {
        return "Validation handling of Receive Process";
    }
}


In this class we now want to add a method for each validation we set up in the configuration.

The first we made was called ValidateLocationReceive, and that is what we will call the method to validate:

ValidateLocationReceive method
	[MobDocumentType(methodStr(MobDocReceiveValidation,ValidateLocationReceive))]
    public str ValidateLocationReceive()
    {
        InventLocationId	warehouse = request.getFieldValue(extendedTypeStr(InventLocationid)); // Get the warehouse from the request
        WmsLocationId		location  = request.getFieldValue('bin'); //Get the Location the user entered from the request

        if (!wmsLocation::exist(location,warehouse)) // Check if location exists
        {
            throw Error (strFmt("Location %1 does not exist on warehouse %2",location,warehouse)); // If it doesn't exist, throw an error
        }
        return 'ok';
    }

Notice the Attribute the method has, this is a way for the system to find the right method to execute.

The code is explained in the comments, and it takes the relevant information from the request sent from the device. It checks if the location exists, and if not, it throws an error the user will be presented with on the device as the validation fails.


The same procedure goes for validation the Quantity received. The request was called ValidateQuantityReceive in the configuration, and we will call our method the same:


ValidateQuantityReceive method
	[MobDocumentType(methodStr(MobDocReceiveValidation,ValidateQuantityReceive))]
    public str ValidateQuantityReceive()
    {
        InventTransId itrsID = request.getFieldValue(MobConstants::LineNumber()); //Find the values from the request
        real qty = str2Num(request.getFieldValue(MobConstants::Quantity()));
        str  backendId = request.getFieldValue(MobConstants::OrderBackendID()); //Puchase order id. Structured like this: purchtable/purchid/000676/receive
        real maxQtyAllowed;

		//Make code here that uses the inventTransId and extracts PurchId from backendid, to find the relevant line, and set max allowed quantity

        if (qty >maxQtyAllowed) // Validate if the quantity entered by the user exceeds the allowed quantity
        {
            throw Error(strFmt("The maximum allowed quantity is %1",maxQtyAllowed));
        }

        return 'ok';
    }

As with the previous method, the principle is that the values are read from the request. The clause for validating the request is found, and if it doesn't comply with the limit set, throw an error.


One final thing needed, is to add attributes to the class declaration, that this class handles these validation requests. This allows the system to automatically detect that this class handles these specific validations, and ensures no further setup is needed on the dynamics side, except creating this class.

The attributes for the class is declared like this:

Class Declaration Attributes
[MobDocumentType(methodStr(MobDocReceiveValidation,ValidateLocationReceive)),
MobDocumentType(methodStr(MobDocReceiveValidation,ValidateQuantityReceive))]
class MobDocReceiveValidation extends MobDocumentHandler
{
.
.
.


That's it. Compile the class and start using the device, and you should have validations on your receipt processes.



The final class looks like this: 

Final class in 365 FO
[MobDocumentType(methodStr(MobDocReceiveValidation,ValidateLocationReceive)),
MobDocumentType(methodStr(MobDocReceiveValidation,ValidateQuantityReceive))]
class MobDocReceiveValidation extends MobDocumentHandler
{

    public MobDocumentHandlerDescription description()
    {
        return "Validation handling of Receive Process";
    }

    [MobDocumentType(methodStr(MobDocReceiveValidation,ValidateLocationReceive))]
    public str ValidateLocationReceive()
    {
        InventLocationId	warehouse = request.getFieldValue(extendedTypeStr(InventLocationid));// Get the warehouse from the request
        WmsLocationId		location  = request.getFieldValue('bin'); //Get the Location the user entered from the request

        if (!wmsLocation::exist(location,warehouse)) // Check if location exists
        {
            throw Error (strFmt("Location %1 does not exist on warehouse %2",location,warehouse)); // If it doesn't exist, throw an error
        }
        return 'ok';
    }

    [MobDocumentType(methodStr(MobDocReceiveValidation,ValidateQuantityReceive))]
    public str ValidateQuantityReceive()
    {
        InventTransId itrsID = request.getFieldValue(MobConstants::LineNumber());//Find the values from the request
        real qty = str2Num(request.getFieldValue(MobConstants::Quantity()));
        str  backendId = request.getFieldValue(MobConstants::OrderBackendID()); //Puchase order id. Structured like this: purchtable/purchid/000676/receive
        real maxQtyAllowed;

        //Make code here that uses the inventTransId and extracts PurchId from backendid, to find the relevant line, and set max allowed quantity

        if (qty >maxQtyAllowed) // Validate if the quantity entered by the user exceeds the allowed quantity
        {
            throw Error(strFmt("The maximum allowed quantity is %1",maxQtyAllowed));
        }

        return 'ok';
    }

}