RF Interface. Development.

Development

We will create simple activity to enquiry retail item price.

1. Add new enum element and name it VKPriceEnquiry. The element name should be same for both enums.
\Data Dictionary\Base Enums\WHSWorkActivity
\Data Dictionary\Base Enums\WHSWorkExecuteMode

2. Create new base enum \Data Dictionary\Base Enums\VKWHSRFPriceEnquiry which will be used to handle state machine steps. First step element enum value should be equal to 1, otherwise standard calcel button will not work.

3. Create class \Classes\VKWHSWorkExecuteDisplayPriceEnquiry which will handle all work. It should extends WHSWorkExecuteDisplay.
Class declaration
class VKWHSWorkExecuteDisplayPriceEnquiry extends WHSWorkExecuteDisplay
{
    #define.RFPriceLabel('PriceLabel')
    #define.RFBtnReset('VKReset')
    #define.RFBtnBack('VKBack')
    InventLocationId        inventLocationId;
}
Add construct method to it
static VKWHSWorkExecuteDisplayPriceEnquiry construct()
{
    VKWHSWorkExecuteDisplayPriceEnquiry   workExecuteDisplayPriceEnquiry;

    workExecuteDisplayPriceEnquiry = new VKWHSWorkExecuteDisplayPriceEnquiry();

    return workExecuteDisplayPriceEnquiry;
}
Main entry method is displayForm:
container displayForm(container _con, str _buttonClicked = '')
{
    container                   con = _con,
                                ret;
    boolean                     proceed = false;

    mode         = WHSWorkExecuteMode::VKPriceEnquiry;
    pass         = WHSRFPassthrough::create(conPeek(_con, #PassthroughInfo));

    InventLocationId = WHSWorkUserSession::find(userId).InventLocationId;

    // Remove all error controls that left from previous state if any
    con = this.removeErrors(con);

    if (!step)
    {
        step = VKWHSRFPriceEnquiry::ItemSelection;
    }

    // Back button
    if (#RFBtnBack == _buttonClicked && step > 1)
    {
        step--;
    }

    // State transition and data update
    if (VKWHSRFPriceEnquiry::ItemSelection == step && #RFOK == _buttonClicked)
    {
        ret = this.updateItem(ret, con);
    }
    else if (VKWHSRFPriceEnquiry::ItemSelection == step && #RFBtnReset == _buttonClicked)
    {
        this.resetPassValue();
    }

    // Build new UI from scratch
    switch (step)
    {
        // This example has only 1 screen. But real world usualy not so simple and you most probably will have several.
        // Add new enum elements and cases here.
        // Using enum will greatly improove support and general understanding of "what is going on here"
        case VKWHSRFPriceEnquiry::ItemSelection:
            ret = this.buildItemSelection(ret, _buttonClicked);
            break;
        default:
            break;
    }


    ret = this.updateModeStepPass(ret, mode, step, pass);

    return ret;
}
Method that will build item selection screen:
container buildItemSelection(container _ret, str _buttonClicked = '')
{
    WHSInventTable      whsInventTable;
    InventTable         inventTable;
    ItemId              itemId;
    InventDim           inventDim;
    boolean             dimCheck;
    RetailStoreTable    retailStoreTable;
    UnitOfMeasureSymbol uom;
    Price               price;

    if (pass.exists(#ItemId))
    {
        itemId = pass.lookupStr(#ItemId);
    }

    if (itemId)
    {
        inventTable = InventTable::find(itemId);
        if (!inventTable)
        {
            itemId = '';
        }
        if (itemId)
        {
            dimCheck    = this.checkInventDim(itemId, false);
        }
    }

    _ret += [this.buildControl(#RFText, #ItemId, "@SYS14428", 1, itemId, extendedTypeNum(ItemId), '', 0, (itemId) ? false : true)];

    if (pass.exists(#ItemId) && pass.lookup(#ItemId) != '')
    {
        whsInventTable = WHSInventTable::find(pass.lookup(#ItemId));

        if (whsInventTable.rfDescription1)
        {
            _ret += [this.buildControl(#RFLabel, #RFDescription1, strFmt('\t        %1', whsInventTable.rfDescription1), 1, '', #WHSRFUndefinedDataType, '', 0, false)];
        }
        else
        {
            _ret += [this.buildControl(#RFLabel, #RFDescription1, strFmt('\t        %1', inventTable.defaultProductName()), 1, '', #WHSRFUndefinedDataType, '', 0, false)];
        }

        if (whsInventTable.rfDescription2)
        {
            _ret += [this.buildControl(#RFLabel, #RFDescription2, strFmt('\t        %1', whsInventTable.rfDescription2), 1, '', #WHSRFUndefinedDataType, '', 0, false)];
        }
    }

    if (itemId)
    {
        _ret = this.buildProductDimensionsDD(_ret, inventTable.ItemId, true);

        _ret = this.buildUOM(_ret, '', false, false, false, pass.lookupStr(#SelectedValueUOM), true);
        // Without this defaulting UoM selection will work only from second hit
        if (!pass.exists(#SelectedValueUOM))
        {
            pass.insert(#SelectedValueUOM, '');
        }

        inventDim = this.getInventDim(itemId, false);
        inventDim = InventDim::findOrCreate(inventDim);

        if (dimCheck && pass.exists(#SelectedValueUOM) && pass.lookup(#SelectedValueUOM) != '' && pass.lookup(#SelectedValueUOM) != inventTable.inventUnitId())
        {
            _ret = this.buildUoMConversionText(_ret, inventTable, inventDim.inventDimId);
        }

        if (dimCheck)
        {
            uom = pass.lookupStr(#SelectedValueUOM);

            if (uom)
            {
                select firstOnly StoreNumber from retailStoreTable
                    where retailStoreTable.inventLocation   == InventLocationId
                        &&retailStoreTable.ChannelType      == RetailChannelType::RetailStore;

                if (retailStoreTable.StoreNumber)
                {
                    price = RetailPricingEngine::getRetailPriceByItem(retailStoreTable.StoreNumber, itemId, uom, inventDim.inventDimId, DateTimeUtil::newDateTime(SystemDateGet(), timeNow()), InventDimCombination::find(itemId, inventDim.inventDimId).RetailVariantId);
                }

                _ret += [this.buildControl(#RFLabel, #RFPriceLabel, strFmt("Price: %1", price), 1, '', #WHSRFUndefinedDataType, '', 0, false)];
            }
        }
    }

    _ret += [this.buildControl(#RFButton, #RFOK, "@SYS5473", 1, '', #WHSRFUndefinedDataType, '', 1)];

    _ret += [this.buildControl(#RFButton, #RFBtnReset, "@SYS3073", 1, '', #WHSRFUndefinedDataType, '', 1)];
    _ret = this.addCancelButton(_ret, true, true);

    return _ret;
}
If you want to select all items not only those that available physically add an exception here \Classes\WHSRFControlData\processControl in case related to #ItemId (case #ItemId:)
                        mode                    != WHSWorkExecuteMode::TransferOrderLineReceiving           &&
                        mode                    != WHSWorkExecuteMode::TransferOrderLineReceivingAndLocate  &&
                        mode                    != WHSWorkExecuteMode::ChangeBatchDisposition               &&
                        mode                    != WHSWorkExecuteMode::VKPriceEnquiry                       &&
                        WHSRFMenuItemTable::getWHSWorkExecuteMode(WHSRFMenuItemTable::find(menuItemName)) != WHSWorkExecuteMode::AdjustmentIn)
Method that processes inbound data.
private container updateItem(container _ret, container _con)
{
    container                   tmpFieldValues,
                                tmp;
    Map                         fieldValues;

    try
    {
        // Update data in pass variable
        [_con, tmpFieldValues]  = WHSRFControlData::processData(_con, pass);
        fieldValues             = WHSRFPassthrough::create(tmpFieldValues);
        pass                    = this.combineMaps(pass, fieldValues);
        // Price enquiry activity does involve any data changes or other actions. But in real life you may want to add some actions here.
        if (this.hasError(_con))
        {
            _ret        = this.copyErrors(_con, _ret);
        }
    }
    catch
    {
        tmp  = this.addErrorLabelFromInfolog(conNull(), infologLine(), WHSRFColorText::Error);
        _ret = this.addTop(_ret, tmp);
    }
    return _ret;
}
Add all general methods from RF Interface. General methods.
4. Add initialization of our newly created class to \Classes\WHSWorkExecuteDisplay\construct
case WHSWorkExecuteMode::VKPriceEnquiry                         : return VKWHSWorkExecuteDisplayPriceEnquiry::construct();

Required setup

1. Warehouse management -> Setup -> Movile device -> Mobile device menu items
Add new menu item with Indirect mode and Activicy code Price enquiry.
2. Check which menu is used by the modile user that you are going to use:
Warehouse management -> Setup -> Work users -> Worker -> Users -> work users grid -> Menu name
3. Add newly created Mobile device menu item to menu.
Warehouse management -> Setup -> Movile device -> Mobile device menu

Result

You can use WHSWorkExecute form to see result.


Search

About

DaxOnline.org is free platform that allows you to quickly store and reuse snippets, notes, articles related to Dynamics AX.

Authors are allowed to set their own AdSense units.
Join us.

Blog Tags