Thursday, 10 September 2015

Report in AX 2012 R3 Mobile Device Portal

This post shows how to provide an SSRS report via Mobile Device Portal in Dynamics Ax 2012 R3. The user will be able to scan an Item ID and the MDP page will show the BOMConsistOf Report for this item. Therefore the report will be rendered as HTML.
First, create a file share on the web server where Dynamics AX can save the HTML File. In my case I’ve created an additional folder in C:\Program Files (x86)\Microsoft Dynamics AX\60\Warehouse Mobile Devices Portal0\ , called it “Report” and set the folder properties in windows explorer to be a file share.
Report folder in Mobile Device Portal
In Dynamics AX Development Workspace, extend the base enums WHSWorkActivity and WHSWorkExecuteModeby adding an additional enumeration value called “ItemInformation”. I’m using the label @SYS113931 for “Item Information”.
Next, create a new class that extends WHSWorkExecuteDisplay
class ERPWHSWorkExecuteDisplayItemInfo extends WHSWorkExecuteDisplay
{
}
The MDP page will include 2 steps, first to scan an ItemId and second to create the report and provide a link. Therefore add 3 methods to the class
// Label and text field for an ItemID container buildStep0(container _con)
{
    xSession    session = new xSession();
    container   ret = _con;
    ret += [this.buildControl(#RFLabel,’Lbl_ItemId’,’Scan Item ID’,1,”,
            #WHSRFUndefinedDataType,”,0)];
    ret += [this.buildControl(#RFText,’ItemId’,"@SYS7407",1,”,
            extendedTypeNum(ItemId),”, 0)];
    ret += [this.buildControl(#RFButton,#RFOK,"@SYS5473",1,”,
            #WHSRFUndefinedDataType,”,1)];
    return ret;
}
// Disabled text field with ItemID and Label with URL to HTML report
container buildStep1(container _con)
{
    xSession    session = new xSession();
    container   ret = _con;
    ret += [this.buildControl(#RFText,’ItemId’,"@SYS7407",1,
            pass.lookup(‘Item’),extendedTypeNum(ItemId),”,0,false)];
    ret += [this.buildControl(#RFLabel,’A_REPORT’, 
            ‘
http://localhost:8080/Report/bom.html’,
            1,”,#WHSRFUndefinedDataType,”,0)]; 

    ret += [this.buildControl(#RFButton,#RFOK,"@SYS5473",1,”,
            #WHSRFUndefinedDataType,”,1)];
    return ret;
}
// Set ItemID range and save report to File
private void createReport()
{
    ItemId itemId = pass.lookup(‘Item’);
    Query query; 
    BOMConsistOfController ctrl = new BOMConsistOfController();
    ctrl.parmReportName(ssrsReportStr(BOMConsistOf,Report));
    query = ctrl.parmReportContract().parmQueryContracts().
            .lookup(‘BOMConsistOfDP_DynamicParameter’);
    SysQuery::findOrCreateRange(query.dataSourceNo(1),
              fieldNum(InventTable,ItemId)).value(itemId); 

    ctrl.parmReportContract().parmPrintSettings()
         .printMediumType(SRSPrintMediumType::File);
    ctrl.parmReportContract().parmPrintSettings()
         .fileFormat(SRSReportFileFormat::HTML4_0);
    ctrl.parmReportContract().parmPrintSettings()
         .parmFileName(@"\\localhost\Report\bom.html");
   
    ctrl.parmReportContract().parmPrintSettings().overwriteFile(true);
    ctrl.run();
}
Add this code the displayForm method
public container displayForm(container _con, str _buttonClicked = ”)
{
    WHSWorkExecute  workExecute = new WHSWorkExecute();
    container       ret = connull();
    container       con = _con;
    int             hasError = 0;
    int             startInfologLine;
    pass = WHSRFPassthrough::create(conPeek(_con, 2));
    hasError = this.hasError(_con);
    if (pass.exists(#UserId))
    {
        userId = pass.lookup(#UserId);
    }
    startInfologLine = infologLine() + 1; 
    switch (step)
    { 
        case 0:             ret = this.buildStep0(ret);
            step = 1;
            break;
        case 1:
            pass.insert(‘Item’, conPeek(conPeek(con, 4 + hasError), #data));
            this.createReport();
            ret = this.buildStep1(ret);
            step = 2;
            break;
        case 2:
            pass = this.resetPassthrough(ret, false);
            ret = this.buildStep0(ret);
            step = 0;
            break;
        default:
            break;
    }
    ret = this.updateModeStepPass(ret,WHSWorkExecuteMode::ERPItemInfo,
          step,pass);
    ret = this.addCancelButton(ret, 1, true);
    return ret;
}
With this code in place the Mobile Device Portal page will show a simple text with the Reports URL. However, to provide a link, some JavaScript code is require. Start Visual Studio (or any other HTML editor) as Admin and open C:\Program Files (x86)\Microsoft Dynamics AX\60\Warehouse Mobile Devices Portal0\Views\Execute\DisplayIEOS.aspx file. At the init() method add this code to hide the label and add a link.
function init() {
    "use strict";
    focusFirstEnabledInput();
    var label = document.getElementById("A_REPORTLbl");
    if(label != null)
    {
        label.style.display = ‘none’;
        var link = document.createElement(‘A’);
        link.setAttribute(‘HREF’,label.outerText);
        link.appendChild(document.createTextNode("Report"));
        label.parentNode.appendChild(link);
    }
}
Make sure to compile your work in X++ and IL and synchronize the Data Dictionary. Restarting the AOS might also be a good idea at this stage.
Finally, configure the new activity to be available in Mobile Device Portal menu. In Dynamics AX 2012 R3 > Warehouse Management > Setup > Mobile Device > Mobile Device Menu Item > Add a new item with Mode:Indirect and Activity Code:Item Information. In Warehouse Management > Setup > Mobile Device > Mobile Device Menu > select inventory and add the newly create menu item.
Open the Mobile Device Portal page, logon, select Inventory Management and Item Information. Provide a valid ItemId which has BOM lines. If you are using Contoso Demo data, item D0007 from company USMF is an example. Next, the SSRS report is create and placed as HTML file. The mobile device portal page will show the link to the HTML report.
SSRS Report as HTML in Mobile Device Portal
BTW: you may use Visual Studio Addins to debug the application