How-to: Online Validation for Line step

Description

Online Validation on Steps can instantly validate the user data, with a call to BC. 

Use cases

  • Tell the user instantly whether an input value is correct
  • Return more additional steps
  • Return value(s) to other existing steps

See also


Overview

Tip

Requirement

For example 1: Android app version 1.9.1

Example 1: Online Validation on Package Number during Picking, return values to multiple steps

In this example, two existing steps (FromBin and Quantity) are updated, when the user enters a Package Number on the order line.


Step 1: Enable Package Number implementation


Step 2: Enable Online Validation

  • Since Package Number is an additional step, as opposed to the Standard Workflow, we an simply catch it and modify it.
  • Setting Onlinevalidation to use a document type named "PackageNumberValidation".


[EventSubscriber(ObjectType::Codeunit, Codeunit::"MOB WMS Pick", 'OnGetPickOrderLines_OnAddStepsToAnyLine', '', true, true)]
    local procedure OnGetPickOrderLines_OnAddStepsToAnyLine(_RecRef: RecordRef; var _BaseOrderLineElement: Record "MOB Ns BaseDataModel Element"; var _Steps: Record "MOB Steps Element")
    begin
        _Steps.SetRange(name, 'PackageNumber');
        if _Steps.FindFirst() then begin
            _Steps.Set_id(1);
            _Steps.Set_onlineValidation('PackageNumberValidation',true);
            _Steps.Save();
        end;
    end;
 
 

Step 3: Create new DocumentType

  • "PackageNumberValidation" needs to be added and point the codeunit that handles online validation.

    [EventSubscriber(ObjectType::Codeunit, Codeunit::"MOB WMS Setup Doc. Types", 'OnAfterCreateDefaultDocumentTypes', '', true, true)]
    local procedure OnAfterCreateDefaultDocumentTypes()
    var
        MobWmsSetupDocTypes: Codeunit "MOB WMS Setup Doc. Types";
    begin
        MobWmsSetupDocTypes.CreateDocumentType('PackageNumberValidation', '', Codeunit::"MOB WMS Whse. Inquiry");
    end;
  
 

Step 4: Write your validation code

  • In this example two steps are being updated, when the user enters a Package Number on the order line.

    [EventSubscriber(ObjectType::Codeunit, Codeunit::"MOB WMS Whse. Inquiry", 'OnWhseInquiryOnCustomDocumentType', '', true, true)]
    local procedure OnWhseInquiryOnCustomDocumentType(_DocumentType: Text; var _RequestValues: Record "MOB NS Request Element"; var _ResponseElement: Record "MOB NS Resp Element"; var _RegistrationTypeTracking: Text; var _IsHandled: Boolean)
    var
        PackageNo, FromBin, Quantity : Text;
    begin
        if _IsHandled then exit;
        if _DocumentType <> 'PackageNumberValidation' then exit;

        // Read collected Package No.
        PackageNo := _RequestValues.GetValue('PackageNumber');

        // To Do:
        // Determine values to use on Bin and Quantity
        Quantity := '99';
        FromBin := 'BinCode';

        // Respond with value for "FromBin"
        _ResponseElement.Create('stepUpdates');
        _ResponseElement.SetValue('stepA/@name', 'FromBin');
        _ResponseElement.SetValue('stepA/@value', 'w-04-0009');
        // IMPORTANT ! 'interactionPermission' is NOT SUPPORTED here. That is ONLY FOR "Quantity" (Mobile App v.1.9.1)

        // Respond with value for "Quantity"
        _ResponseElement.SetValue('stepB/@name', 'Quantity');
        _ResponseElement.SetValue('stepB/@value', Format(Quantity));
        _ResponseElement.SetValue('stepB/@interactionPermission', Format(enum::"MOB ValueInteractionPermission"::AllowEdit)); //ApplyDirectly,AllowEdit or VerifyOnly

        _IsHandled := true;
    end;


Example 2: Online Validation on Receiving or Picking

In this example we will add all the available online validations to the Receive or Pick function. But you can do this for other Planned functions i.e. Put-away, Ship, Move, Count, Assembly or Production.

Step 1: Enable Online Validation

Receive: Add <validation> to Receive Service.

Mobile configuration application.cfg
<service id="Receive" type="Order" orderType="Receive">
  <requests>
    <..>
  </requests>
   
  <validation>
    <lotNumberValidation online="true" documentName="ValidateMyLotNumber" includeCollectedValues="true"/> 
    <serialNumberValidation online="true" documentName="ValidateMySerial" validationLevel="Item" includeCollectedValues="true"/>
    <toBinValidation online="true" documentName="ValidateMyToBin" includeCollectedValues="true"/>
    <quantityValidation online="true" documentName="ValidateMyQuantity" includeCollectedValues="true"/>
  </validation>  
</service>


or Pick: Add <validation> to Pick Service:

Mobile configuration application.cfg
<service id="Pick" type="Order" orderType="Pick">
  <requests>
   <..>
  </requests>

  <validation>
 	<lotNumberValidation online="true" documentName="ValidateMyLotNumber" includeCollectedValues="true"/> 
    <serialNumberValidation online="true" documentName="ValidateMySerial" validationLevel="Item" includeCollectedValues="true"/>
	<fromBinValidation online="true" documentName="ValidateMyFromBin" includeCollectedValues="true"/>
	<toteValidation online="true" documentName="ValidateMyTote" includeCollectedValues="true"/>
 	<quantityValidation online="true" documentName="ValidateMyQuantity" includeCollectedValues="true"/> 
   </validation>
</service>

See  Mobile Configuration Files for how to edit application.cfg and training on https://university.taskletfactory.com/


Step 2: Add "Mobile Document Type" and add it to "Mobile Group"

The system needs to know which codeunit will process the validations. You could set up this manually using "Mobile Document Types".

But you should use OnAfterCreateDefaultDocumentTypes event

 

     // Add Mobile Document Types
    [EventSubscriber(ObjectType::Codeunit, Codeunit::"MOB WMS Setup Doc. Types", 'OnAfterCreateDefaultDocumentTypes', '', true, true)]
    local procedure My01OnAfterCreateDefaultDocumentTypes()
    var
        MobWmsSetupDocTypes: Codeunit "MOB WMS Setup Doc. Types";
    begin
        // Create and name document types
        MobWmsSetupDocTypes.CreateDocumentType('ValidateMyLotNumber', '', Codeunit::"MOB WMS Whse. Inquiry");
        MobWmsSetupDocTypes.CreateDocumentType('ValidateMySerial', '', Codeunit::"MOB WMS Whse. Inquiry");
        MobWmsSetupDocTypes.CreateDocumentType('ValidateMyToBin', '', Codeunit::"MOB WMS Whse. Inquiry");
        MobWmsSetupDocTypes.CreateDocumentType('ValidateMyFromBin', '', Codeunit::"MOB WMS Whse. Inquiry");
        MobWmsSetupDocTypes.CreateDocumentType('ValidateMyTote', '', Codeunit::"MOB WMS Whse. Inquiry");
        MobWmsSetupDocTypes.CreateDocumentType('ValidateMyQuantity', '', Codeunit::"MOB WMS Whse. Inquiry");
    end;


Failing to do so will result in the following error:

 


Step 3: Write your validation code

Using OnWhseInquiryOnCustomDocumentType


    // Write validation code
    [EventSubscriber(ObjectType::Codeunit, Codeunit::"MOB WMS Whse. Inquiry", 'OnWhseInquiryOnCustomDocumentType', '', true, true)]
    local procedure My01OnWhseInquiryOnCustomDocumentType(_DocumentType: Text; var _RequestValues: Record "MOB NS Request Element"; var _ResponseElement: Record "MOB NS Resp Element"; var _RegistrationTypeTracking: Text; var _IsHandled: Boolean)
    begin
        if _IsHandled then
            exit;

        // Using ERROR() is the correct way to fail the validation, otherwise the validation was OK

        case _DocumentType of
            // These examples displays misc. request values for illustration purposes

            'ValidateMyLotNumber':
                Error('OrderNo: %1\ LineNo: %2\ LineItem: %3\ LotStep: %4\ ExpDateStep: %5',
                _RequestValues.Get_OrderBackendID(),
                _RequestValues.Get_LineNumber(),
                _RequestValues.Get_ItemNumber(), // Currently Not Supported by Android App 1.8.0.1
                _RequestValues.Get_LotNumber(),
                _RequestValues.Get_ExpirationDate()); // ExpirationDate-step will not trigger validation itself. But it is included when Lot-step is validated

            'ValidateMySerial':
                Error('OrderNo: %1\ LineNo:%2\ LineItem: %3\ SerialStep: %4',
                _RequestValues.Get_BackendID(),
                _RequestValues.Get_LineNumber(),
                _RequestValues.Get_ItemNumber(),
                _RequestValues.Get_SerialNumber());

            // Note: ToBin validation on receive must typically be enabled using "OnGetReceiveOrderLines_OnAfterSetFrom.." events
            'ValidateMyToBin':
                Error('OrderNo: %1\ LineNo:%2\ LineItem: %3\ BinStep: %4',
                _RequestValues.Get_OrderBackendID(),
                _RequestValues.Get_LineNumber(),
                _RequestValues.Get_ItemNumber(),
                _RequestValues.Get_Bin());

            'ValidateMyFromBin':
                Error('OrderNo: %1\ LineNo:%2\ LineItem: %3\ BinStep: %4',
                _RequestValues.Get_OrderBackendID(),
                _RequestValues.Get_LineNumber(),
                _RequestValues.Get_ItemNumber(),
                _RequestValues.Get_Bin());

            // Note: Tote is typically only used on Picking
            'ValidateMyTote':
                Error('OrderNo: %1\ LineNo: %2\ LineItem: %3\ ToteStep: %4',
                _RequestValues.Get_OrderBackendID(),
                _RequestValues.Get_LineNumber(),
                _RequestValues.Get_ItemNumber(), // Currently Not Supported by Android App 1.8.0.1
                _RequestValues.Get_ToteID());

            'ValidateMyQuantity':
                Error('OrderNo: %1\ LineNo: %2\ LineItem: %3\ QuantityStep: %4',
                _RequestValues.Get_OrderBackendID(),
                _RequestValues.Get_LineNumber(),
                _RequestValues.Get_ItemNumber(),
                _RequestValues.Get_Quantity());
        end;

        // Validation was OK
        _IsHandled := true;
    end;

Viewing the result

Mobile will display a message to the mobile user that online validation has failed, including the error message.


Example 3: Online Validation on Custom Workflow

In this example we will add onlinevalidation on a custom Planned functions /wiki/spaces/SD/pages/78939861 

Step 1: Define Line Step(s)

Define a new Workflow step in application.cfg

Mobile configuration application.cfg
<..>
<workflow>
  <configuration>
      <steps>
        <..leave existing steps here..>
        <text id="1" name="MyTextStep" header="Scan text" helpLabel="Please scan" autoForwardAfterScan="true" eanAi="00" optional="false" primaryInputMethod="Scan">
          <onlineValidation online="true" documentName="ValidateMyCustomWorkflowStep" includeCollectedValues="true"/>
        </text>


Step 2: Create new DocumentType

See example one for details.

    // Add Mobile DocumentType to handle validation code
    [EventSubscriber(ObjectType::Codeunit, Codeunit::"MOB WMS Setup Doc. Types", 'OnAfterCreateDefaultDocumentTypes', '', true, true)]
    local procedure My02OnAfterCreateDefaultDocumentTypes()
    var
        MobWmsSetupDocTypes: Codeunit "MOB WMS Setup Doc. Types";
    begin
        MobWmsSetupDocTypes.CreateDocumentType('ValidateMyWorkflowStep', '', Codeunit::"MOB WMS Whse. Inquiry");
    end;

Step 3: Write your validation code

 Using OnWhseInquiryOnCustomDocumentType

 // Implement DocumentType
    [EventSubscriber(ObjectType::Codeunit, Codeunit::"MOB WMS Whse. Inquiry", 'OnWhseInquiryOnCustomDocumentType', '', true, true)]
    local procedure My02OnWhseInquiryOnCustomDocumentType(_DocumentType: Text; var _RequestValues: Record "MOB NS Request Element"; var _ResponseElement: Record "MOB NS Resp Element"; var _RegistrationTypeTracking: Text; var _IsHandled: Boolean)
    begin
        if _IsHandled then
            exit;


        if _DocumentType = 'ValidateMyWorkflowStep' then
            Error('MyTextStep: %1\ OrderNo: %2\ LineNo: %3',
              _RequestValues.GetValue('MyTextStep'),
              _RequestValues.Get_BackendID(),
              _RequestValues.Get_LineNumber());

        _IsHandled := true;
    end;


Example 4: Online Validation on Custom Line Step

In this example, we will add online validation to a Line step we ourselves have added to an existing Planned Functions e.g. Receive, Pick, Put-away etc.

Step 1: Define Line Step(s)

Using OnGetReferenceData_OnAddRegistrationCollectorConfigurations

 

// Define step
    [EventSubscriber(ObjectType::Codeunit, Codeunit::"MOB WMS Reference Data", 'OnGetReferenceData_OnAddRegistrationCollectorConfigurations', '', true, true)]
    local procedure My03OnGetReferenceData_OnAddRegistrationCollectorConfigurations(var _Steps: Record "MOB Steps Element")
    begin
        // Define a key to hold the step
        _Steps.InitConfigurationKey('MyPickStep');

        // Define a text step
        _Steps.Create_TextStep(10, 'MyTextStep');
        _Steps.Set_header('Header text');
        _Steps.Set_label('Label text');
        _Steps.Set_helpLabel('Help text');

        // Enabled Online Validation and setting a DocumentType
        _Steps.Set_onlineValidation('ValidateMyPickStep', true);
    end;

Step 2: Add steps to Pick-function

Using OnGetPickOrderLines_OnAddStepsToAnyLine

    // Add steps Pick Lines
    [EventSubscriber(ObjectType::Codeunit, Codeunit::"MOB WMS Pick", 'OnGetPickOrderLines_OnAddStepsToAnyLine', '', true, true)]
    local procedure My03OnGetPickOrderLines_OnAddStepsToAnyLine(_RecRef: RecordRef; var _BaseOrderLineElement: Record "MOB NS BaseDataModel Element")
    begin
        _BaseOrderLineElement.Create_StepsByReferenceDataKey('MyPickStep', true);
    end;

Step 3: Create new DocumentType

    // Add Mobile DocumentType to handle validation code
    [EventSubscriber(ObjectType::Codeunit, Codeunit::"MOB WMS Setup Doc. Types", 'OnAfterCreateDefaultDocumentTypes', '', true, true)]
    local procedure My03OnAfterCreateDefaultDocumentTypes()
    var
        MobWmsSetupDocTypes: Codeunit "MOB WMS Setup Doc. Types";
    begin
        MobWmsSetupDocTypes.CreateDocumentType('ValidateMyPickStep', '', Codeunit::"MOB WMS Whse. Inquiry");
    end;

Step 4: Write your validation code

    // Implement DocumentType
    [EventSubscriber(ObjectType::Codeunit, Codeunit::"MOB WMS Whse. Inquiry", 'OnWhseInquiryOnCustomDocumentType', '', true, true)]
    local procedure My03OnWhseInquiryOnCustomDocumentType(_DocumentType: Text; var _RequestValues: Record "MOB NS Request Element"; var _ResponseElement: Record "MOB NS Resp Element"; var _RegistrationTypeTracking: Text; var _IsHandled: Boolean)
    begin
        if _IsHandled then
            exit;


        if _DocumentType = 'ValidateMyPickStep' then
            Error('MyTextStep: %1\ OrderNo: %2\ LineNo: %3',
              _RequestValues.GetValue('MyTextStep'),
              _RequestValues.Get_BackendID(),
              _RequestValues.Get_LineNumber());

        _IsHandled := true;
    end;


Example 5: Online Validation with confirm-dialog on receive quantity step

Requirement

Android app version 1.5.11.1

In this example we will add onlinevalidation to the standard Quantity Line step and ask the user to confirm if the quantity exceeds the expected. 

See also: How-to: Add Line Step

This is how the process looks from mobile

Step 1: Enable Online Validation

Add <validation> tag to Receive:

Mobile configuration application.cfg
<service id="Receive" type="Order" orderType="Receive">
  <requests>
    <..>
  </requests>
  <validation>
    <quantityValidation online="true" documentName="ValidateMyQuantity" includeCollectedValues="true"/>
  </validation>  
</service>

See  Mobile Configuration Files for how to edit application.cfg and training on https://university.taskletfactory.com/

Step 2: Turn off OverDeliveryValidation

To allow for greater quantity than expected. See more Register unexpected Quantity (overDeliveryValidation / underDeliveryValidation)

Using OnGetReceiveOrderLines_OnAfterSetFromAnyLine

    // Turn off OverDeliveryValidation warning
    [EventSubscriber(ObjectType::Codeunit, Codeunit::"MOB WMS Receive", 'OnGetReceiveOrderLines_OnAfterSetFromAnyLine', '', true, true)]
    local procedure My04OnGetReceiveOrderLines_OnAfterSetFromAnyLine(_RecRef: RecordRef; var _BaseOrderLineElement: Record "MOB NS BaseDataModel Element")
    begin
        _BaseOrderLineElement.Set_OverDeliveryValidation('None');
    end;

Step 3: Create new DocumentType

    // Add Mobile Document Types
    [EventSubscriber(ObjectType::Codeunit, Codeunit::"MOB WMS Setup Doc. Types", 'OnAfterCreateDefaultDocumentTypes', '', true, true)]
    local procedure My04OnAfterCreateDefaultDocumentTypes()
    var
        MobWmsSetupDocTypes: Codeunit "MOB WMS Setup Doc. Types";
    begin
        // Create and name relevant validation document 
        MobWmsSetupDocTypes.CreateDocumentType('ValidateMyQuantity', '', Codeunit::"MOB WMS Whse. Inquiry");
    end;

Step 4: Write your validation code   

    // Implement DocumentType

    [EventSubscriber(ObjectType::Codeunit, Codeunit::"MOB WMS Whse. Inquiry", 'OnWhseInquiryOnCustomDocumentType', '', true, true)]
    local procedure My04OnWhseInquiryOnCustomDocumentType(_DocumentType: Text; var _RequestValues: Record "MOB NS Request Element"; var _ResponseElement: Record "MOB NS Resp Element"; var _RegistrationTypeTracking: Text; var _IsHandled: Boolean)
    var
        WarehouseReceiptLine: Record "Warehouse Receipt Line";
        PerformValidation: Boolean;
    begin
        if _IsHandled then
            exit;

        if _DocumentType <> 'ValidateMyQuantity' then // DocumentType is derived from <validation> node in application.cfg
            exit;

        // This code is only for Receive-service. Could be Pick, PutAway, Ship, Move etc.
        if _RequestValues.Get_OrderType() <> 'Receive' then // Ordertype is derived from <Service> node in application.cfg
            exit;

        // "Force" is only present when a dialog was Confirmed OK by user
        PerformValidation := (not _RequestValues.Get_Force()) and
                             // Get source document line being registered
                             WarehouseReceiptLine.Get(_RequestValues.Get_OrderBackendID(), _RequestValues.Get_LineNumber());

        if PerformValidation then
            if _RequestValues.Get_Quantity() > WarehouseReceiptLine."Qty. Outstanding (Base)" then
                // "ForceWarning:" will trigger the confirm dialog
                Error('ForceWarning:%1 is more than %2.\\Is this correct?', _RequestValues.Get_Quantity(), WarehouseReceiptLine."Qty. Outstanding (Base)");

        _IsHandled := true;
    end;