How-to: Add action to Order Line menu

Description

Add a new Unplanned Function as action on Pick Lines. 

Use case

This example shows transfers values from an Order Line to a new unplanned function.

This example results in

  • One new Unplanned Functions
    • One action on "Pick Lines" to this function
  • Three Header-fields
    • That transfers Location, Bin and Item from the Order line
  • A step to collect a decimal value from the user


Using the transferred values when adding the step

We use the transferred values when adding the decimal step:

  • The registered (not yet posted) quantity is compared to the full line quantity
  • The result is suggested as Default Value in the step


Step 1: Defining a new Unplanned function 

This part requires you to edit the Mobile Configuration Files

Add this section in the <pages> tag.

<!-- Custom -->
<page id="UnableToPick" type="UnplannedItemRegistration" icon="mainmenunegativeadjustment">
    <title defaultValue="Unable To Pick"/>
    <unplannedItemRegistrationConfiguration type="UnableToPick">
    <header configurationKey="UnableToPick" automaticAcceptOnOpen="true"/>
  </unplannedItemRegistrationConfiguration>
</page>
<!-- Custom -->

We want to add this to the existing Pick Lines page in the Action Menus Then add this section to the <actions> tag of Pick Lines page:
<page id=Picklines...>
<...>
<actions>
  <!-- Custom --> 
    <open id="UnableToPick" icon="mainmenunegativeadjustment" title="Unable To Pick"/>
  <!-- Custom -->

Step 2: Define Header and header fields

Unplanned functions uses Header-fieldsto determine which Steps to collect.

In this step you must define which header fields you want the user to see.

Subscribe to this event

OnGetReferenceData_OnAddHeaderConfigurations
 [EventSubscriber(ObjectType::Codeunit, Codeunit::"MOB WMS Reference Data", 'OnGetReferenceData_OnAddHeaderConfigurations', '', true, true)]
    local procedure MynGetReferenceData_OnAddHeaderConfigurations(var _HeaderFields: Record "MOB HeaderField Element")
    begin
        _HeaderFields.InitConfigurationKey('UnableToPick'); // Name of Header

        // Add Header fields
        // Using pre-defined helper-functions makes it easy to transfer values as field names match 100%
        _HeaderFields.Create_ListField_Location(10);    // 'Location' is a known field on OrderLines response
        _HeaderFields.Set_locked(true);

        _HeaderFields.Create_TextField_FromBin(20);     // 'FromBin' is a known field on OrderLines response
        _HeaderFields.Set_locked(true);

        _HeaderFields.Create_TextField_ItemNumber(30);  // 'ItemNumber' is a known field on OrderLines response
        _HeaderFields.Set_locked(true);
    end;

Step 3: Return Steps to collect

When the header is accepted a new request is made for which Steps to collect, called  "GetRegistrationConfiguration".

Subscribe to this event

OnGetRegistrationConfiguration_OnAddSteps

    [EventSubscriber(ObjectType::Codeunit, Codeunit::"MOB WMS Adhoc Registr.", 'OnGetRegistrationConfiguration_OnAddSteps', '', true, true)]
    local procedure CollectFailedQty(_RegistrationType: Text; var _HeaderFieldValues: Record "MOB NS Request Element"; var _Steps: Record "MOB Steps Element"; var _RegistrationTypeTracking: Text)
    var
        MobToolbox: Codeunit "MOB Toolbox";
        UnableToPickQuantity: Decimal;
    begin
        // Handle only this type
        if _RegistrationType <> 'UnableToPick' then
            exit;

        // Reading Header values (not needed in this example)
        // _HeaderFieldValues.Get_Location();                      // Helper functions exists for common names
        // _HeaderFieldValues.GetValue('AnyField');             // Any custom name
        // _HeaderFieldValues.GetValueAsDecimal('AnyField');   // Get a value as decimal

        // Reading context values inherited from Order Lines


        // Calculate suggested quantity that was unable to be picked
        UnableToPickQuantity := _HeaderFieldValues.GetContextValueAsDecimal('Quantity') -           // The remaining quantity to be picked
                                _HeaderFieldValues.GetContextValueAsDecimal('RegisteredQuantity');            // Subtract the currently registered quantity, not-yet-posted  (if any)


        // Create "Decimal Step" to collect the failed quantity
        _Steps.Create_DecimalStep(10, 'UnableToPickQuantity', false);
        _Steps.Set_header('Unable to pick');
        _Steps.Set_label('Quantity:');
        _Steps.Set_helpLabel('Please input the quantity you were unable to pick');

        _Steps.Set_defaultValue(UnableToPickQuantity);          // Suggest our calculated value as DefaultValue
        _Steps.Set_minValue(0.0000000001);                            // Must be a positive number
        _Steps.Set_eanAi(MobToolbox.GetQuantityGS1Ai());    // Set AI to quantity (310,30,37) so GS1 barcodes scans directly into the step

        // (Create more steps here)
    end;


If you fail to perform this step, you will receive this error.

 


Step 4: Handle posting

You can now run your function from Mobile.

  • Steps has been collected and you press "Accept". Now request is made to "Post" the information ("PostAdhocRegistration")
  • In this step you must read the collected values and post them to the database


XML Example of the Post Request
<?xml version="1.0" encoding="utf-8"?>
<request name="PostAdhocRegistration" created="2020-02-14T15:24:24+01:00" xmlns="http://schemas.microsoft.com/Dynamics/Mobile/2007/04/Documents/Request">
  <requestData name="PostAdhocRegistration">
    <MyDate>14-02-2020</MyDate>
    <MyText>2</MyText>
    <MyDecimal>4</MyDecimal>
    <MyDateStep>14-02-2020</MyDateStep>
    <MyTextStep>2</MyTextStep>
    <MyDecimalStep>4</MyDecimalStep>
    <RegistrationType>MyUnplanned</RegistrationType>
  </requestData>
</request>

Note how both Header values and Steps values are available. in the XML.



Subscribe to OnPostAdhocRegistrationOnCustomRegistrationType

  • The values are extracted from the _RequestValues parameter using "GetValue "functions.


    [EventSubscriber(ObjectType::Codeunit, Codeunit::"MOB WMS Adhoc Registr.", 'OnPostAdhocRegistrationOnCustomRegistrationType', '', true, true)]
    local procedure MyOnPostAdhocRegistrationOnCustomRegistrationType(_RegistrationType: Text; var _RequestValues: Record "MOB NS Request Element"; var _CurrentRegistrations: Record "MOB WMS Registration";
     
var _SuccessMessage: Text; var _RegistrationTypeTracking: Text; var _IsHandled: Boolean)
    begin
        // Handle only this type
        if _RegistrationType <> 'UnableToPick' then
            exit;


        if _IsHandled then
            exit;

        // << Perform your own logic here >>


        // To illustrate the values are collected in this example, the values are used in the success-message and thus displayed to the user
        _SuccessMessage := StrSubstNo('Document %1 Line %2 failed to pick %3', // Display the collected values
                                                                            _RequestValues.GetValueOrContextValue('OrderBackendId'),    // Order Mo.
                                                                            _RequestValues.GetValueOrContextValue('LineNumber'),          // LineNumber
                                                                            _RequestValues.GetValueAsDecimal('UnableToPickQuantity'));  // The collected value

        _RegistrationTypeTracking := 'Tracking info for the Document queue.';
        _IsHandled := true;
    end;


Step 5: Set tracking info (optional)

The parameter _RegistrationTypeTracking can be used to make the Document Queue display additional information about your process.





Common error messages



"No document handler is available for GetRegistrationConfiguration::XYZ"

Error occurs when Accepting the header.

Solution

No steps are returned.

See Step 3.


"No document handler is available for GetRegistrationConfiguration:XXX/XmlSteps"

Solution

No steps are returned.

See Step 3.


"No document handler is available for PostAdhocRegistrationConfiguration::XYZ"

Error occurs when posting.

Solution

Posting is not handled.

See step 4


More examples


Pick in Main menu

The action on Pick Lines

Step 1 adds the action to Pick lines

Unplanned function Header

Step 2 adds header fields

Unplanned function Steps


Step 3 add the steps

Posting

Step 4 handles posting and displays message