Search This Blog

Monday, February 20, 2012

Ax2012 Calling Query Service by using MetaDataService


Using MetaDataService and QueryService

Call the query from metadataService and Define the Range  by using MetaDataQuery  and define the ranges and assign to the queryMetaData and call ExecuteQuery by using QueryService client.

Before doing this sample change the table property of ValidaTimeStateFieldType to yes.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using krishh_cosumeQueryService.QueryService;
using System.Data;
using krishh_cosumeQueryService.MetaDataService;
using System.Runtime.Serialization;
using System.IO;

namespace krishh_cosumeQueryService
{
   public class TestQueryMetaDataService
    {
        static void Main(string[] args)
        {
            DateTime startDate = new DateTime(2011, 01, 01);
            // converts the DateTime to UTC date Time
            startDate = startDate.ToUniversalTime();
            DateTime endDate = new DateTime(2012, 3, 31);
            // converts the DateTime to UTC date Time
            endDate = endDate.ToUniversalTime();
           
            DataSet dataSet;
            Paging paging = null;

            QueryServiceClient client = new QueryServiceClient();
            AxMetadataServiceClient metadataClient = new AxMetadataServiceClient();

            // create query object for QueryService
            QueryService.QueryMetadata queryServiceMetaData = new QueryService.QueryMetadata();
           
            // Create the query object for metadata
            MetaDataService.QueryMetadata queryMetadata = new MetaDataService.QueryMetadata();

            // Get the query from the AOT using the metadata service.
            queryMetadata = metadataClient.GetQueryMetadataByName(new[] { "Cust" })[0];

            // Set the date range on the query.
            queryMetadata.ValidTimeStateQueryType =
            MetaDataService.ValidTimeStateQueryType.Range;
            queryMetadata.ValidTimeStateValidFromDateTime =startDate;
            queryMetadata.ValidTimeStateValidToDateTime = endDate;

            using (MemoryStream memoryStream = new MemoryStream())
            {
                DataContractSerializer mdsSerializer = new
                 DataContractSerializer(typeof(MetaDataService.QueryMetadata));
                DataContractSerializer qsSerializer = new
                  DataContractSerializer(typeof(QueryService.QueryMetadata));
                mdsSerializer.WriteObject(memoryStream, queryMetadata);
                memoryStream.Seek(0, SeekOrigin.Begin);
                queryServiceMetaData =  
               (QueryService.QueryMetadata)qsSerializer.ReadObject(memoryStream);

            }
            // Call the query service with the query retrieved
            // from the metadata service.
            dataSet = client.ExecuteQuery(queryServiceMetaData, ref paging);

            DataTable CustTable = new DataTable();
            CustTable = dataSet.Tables["CustTable"];

            // Loop through the TestEmployee table and display the results.
            if (CustTable != null && CustTable.Rows.Count > 0)
            {
                foreach (DataRow row in CustTable.Rows)
                {
                    Console.WriteLine(row["AccountNum"].ToString() +
                        "\t" + row["CustGroup"].ToString() + "\t" +
                        row["ValidFrom"].ToString() + "\t" +
                        row["ValidTo"].ToString());
                }
                Console.ReadLine();
            }

        }
    }
}

AX2012 Call Query Service with Static Query


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using krishh_cosumeQueryService.QueryService;
using System.Data;

namespace krishh_cosumeQueryService
{
    class TestStaticQuery
    {
        static void Main(string[] args)
        {
            QueryServiceClient client = new QueryServiceClient();
            DataSet dataSet;
            Paging paging=null;

            dataSet = client.ExecuteStaticQuery("CustTable", ref paging);

        }
    }
}
Result-

When we execute the program we got the dataset with the 3tables -CustTable,CustTrans,CustTransOpen.
We can load these tables in the grid if we use the windowsformapplication.

AX2012 Consume Query Service


Consume QueryService and get the results as same as our AOT Queryrun.
The following sample is used to display the customer records with the custgroup ranges.
Create the .Net Solution and add the console project for that solution and write the following program.

before writing the following code we have to take the service reference  http://localhost:8101/DynamicsAx/Services/QueryService.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using krishh_cosumeQueryService.QueryService;
using System.Data;
namespace krishh_cosumeQueryService
{
    class TestQueryService
    {
        static void Main(string[] args)
        {
            QueryServiceClient client = new QueryServiceClient();
            DataSet dataSet;

            //Set up paging so that 500 records are retrieved at a time
            Paging paging = new ValueBasedPaging() { RecordLimit = 500 };

            // Query object
            QueryMetadata query;
            //Datasource for the query
            QueryDataSourceMetadata CustTableds;
            // Ranges for the datasource
            QueryDataRangeMetadata range1, range2;
            //sorting object for the Datasource
            QueryDataOrderByMetadata sort;
            //fields for the query
            QueryDataFieldMetadata accountNum, bankAccount, commissionGroup, cashDisc, custGroup;

            query = new QueryMetadata();

            // Set the properties of the query.
            query.QueryType = QueryType.Join;

            query.DataSources = new QueryDataSourceMetadata[1];
            // Set the properties of the Customers data source.
            CustTableds = new QueryDataSourceMetadata();

            CustTableds.Name = "Customers DataSource";
            CustTableds.Enabled = true;
            //Add teh Table to the Datasource
            CustTableds.Table = "CustTable";

            //Add the data source to the query.
            query.DataSources[0] = CustTableds;
            // Setting DynamicFieldList property to false so I can specify only a few fields

            CustTableds.DynamicFieldList = false;

            CustTableds.Fields = new QueryDataFieldMetadata[5];

            //Add my fields
            accountNum = new QueryDataFieldMetadata();
            accountNum.FieldName = "AccountNum";
            accountNum.SelectionField = SelectionField.Database;
            CustTableds.Fields[0] = accountNum;


            bankAccount = new QueryDataFieldMetadata();
            bankAccount.FieldName = "BankAccount";
            bankAccount.SelectionField = SelectionField.Database;
            CustTableds.Fields[1] = bankAccount;

            commissionGroup = new QueryDataFieldMetadata();
            commissionGroup.FieldName = "CommissionGroup";
            commissionGroup.SelectionField = SelectionField.Database;
            CustTableds.Fields[2] = commissionGroup;

            cashDisc = new QueryDataFieldMetadata();
            cashDisc.FieldName = "CashDisc";
            cashDisc.SelectionField = SelectionField.Database;
            CustTableds.Fields[3] = cashDisc;

            custGroup = new QueryDataFieldMetadata();
            custGroup.FieldName = "CustGroup";
            custGroup.SelectionField = SelectionField.Database;
            CustTableds.Fields[4] = custGroup;


            //Add a range restriction on the query
            range1 = new QueryDataRangeMetadata();
            range1.TableName = "CustTable";
            range1.FieldName = "CustGroup";
            range1.Value = "DK Cust";
            range1.Enabled = true;

            range2 = new QueryDataRangeMetadata();
            range2.TableName = "CustTable";
            range2.FieldName = "CustGroup";
            range2.Value = "Empl";
            range2.Enabled = true;

            // add the ranges to the datasource
            CustTableds.Ranges = new QueryDataRangeMetadata[2];
            CustTableds.Ranges[0] = range1;
            CustTableds.Ranges[1] = range2;

            //Add a sort order on Customer Account number
            sort = new QueryDataOrderByMetadata();
            sort.DataSource = "Customers DataSource";
            sort.FieldName = "AccountNum";
            sort.SortOrder = SortOrder.Ascending;

            query.OrderByFields = new QueryOrderByMetadata[1];
            query.OrderByFields[0] = sort;
            // Execute the query
            int i = 0;
            do
            {
                dataSet = client.ExecuteQuery(query, ref paging);
                Console.WriteLine("Number of Records in CustTable: " + dataSet.Tables[0].Rows.Count.ToString());
                for(int J=0;J<dataSet.Tables[0].Rows.Count;J++)
                {
                    DataRow firstReturnedRow = dataSet.Tables[i].Rows[J];
                    Console.WriteLine("accountnum=" + firstReturnedRow[0].ToString());
                    Console.WriteLine("CustGroup=" + firstReturnedRow[4].ToString());
                }
                i++;
            }
            while (((ValueBasedPaging)paging).Bookmark != null);
            Console.ReadLine();
        }
    }
}

AX2012 Consume DocumentServices using .Net

Call Vendor service to create vendor in AX.
Create ConsoleApplication  in .net evironment and add the servicereference vendVendTableService, and write the following code.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ConsoleApplication9.Vendors;
namespace krishh_VendTableIntegration
{
    class VendServiceIntegration
    {
        static void Main(string[] args)
        {
            VendTableServiceClient vendClient= new VendTableServiceClient();
            CallContext context = new CallContext();
            context.Company = "CEE";  
            AxdVendTable vendor = new AxdVendTable();
             AxdEntity_VendTable[] vendTables = new AxdEntity_VendTable[1];
            AxdEntity_VendTable vendTable = new AxdEntity_VendTable();
          //If your number sequences for vendor accounts are set to manual set this property           
            //vendTable.AccountNum = "30001"; 
         // make sure this currency must be available in your currencies list
          vendTable.Currency = "DKK";      
        // make sure this vendgroup must be available in you master vendgroup    
          vendTable.VendGroup = "10";
          
          vendTable.Name = "www.captivatesolutions.com";
           //Create the party record
           AxdEntity_DirPartyTable_DirPerson party = new AxdEntity_DirPartyTable_DirPerson();
          party.NameAlias = "Krishna";
          //Set the name fields
          AxdEntity_PersonName personName = new AxdEntity_PersonName();
         personName.FirstName = "Krishna";
        personName.MiddleName = "Reddy";
        personName.LastName = "Mod";
      //Add the PersonName Enrtity to the party record and set the name sequence
       party.PersonName = new AxdEntity_PersonName[1] { personName };
      // this sequence will set you name display order
     party.NameSequence = "FirstLast";           
    // add the dirparty to the vendor
    vendTable.DirPartyTable = new AxdEntity_DirPartyTable_DirPartyTable[1] { party };
   vendTables[0] = vendTable;
   vendor.VendTable = vendTables;
  vendClient .create(context, vendor);
        }
    }
}
Same way we can integrate customer as well.

AX2012 Financial journal Dimension Table Relations.



The view DimensionAttributeLevelValueView gives you the individual segments entered in a journal including the main account and each of the selected financial dimensions.  There is a record created in the view for each segment of the transaction.
  For example, if you create a payment journal and enter the vendor and two financial dimensions under the Financial dimensions button there will be 3 records in this view for that transaction.  The DisplayValue field in the view will show you the dimension you selected and all 3 of the records in the view will have the same value in the ValueCombinationRecId field.
The ValueCombinationRecId field in the DimensionAttributeLevelValueView = the RecId from the DimensionAttributeValueCombination table.  The DimensionAttributeValueCombination table stores all of the dimensions including the main account as a string in the DisplayValue field.  The RecId from the DimensionAttributeValueCombination is saved on the LedgerJournalTrans table in the LedgerDimension field.
Also in the DimensionAttributeLevelValueView view the DimensionAttribute field is the RecId of the DimensionAttribute table.  The DimensionAttribute table defines the dimension that the transaction is based on. 
 For example, if you are creating a payment journal the entity is coming from the VendTable.  You can find the entity type/table for the record (like VendTable) by querying the DimensionAttribute table using the DimensionAttribute field in the DimensionAttributeLevelValueView and retrieving the BackingEntityTableName field.  The EntityInstance field in the DimensionAttributeLevelValueView = RecId from the record in the BackingEntityTableName table.  In the case of a payment journal the EntityInstance returns a RecId from the VendTable.

Ax2012 Office Addins Restrictions


There are some restrictions that are inherit with using the Office Add-ins.

Document Services

Document Services are based on a query that defines their structure. Only certain query structures are supported. The following are the restrictions on queries that form the basis of document services. Services which violate these rules may be added to the document data sources form by the administrator, but will result in errors when accessed in the add-in. For this reason it is important that developers and administrators test services for use with the add-in prior to adding them to this form.
·         Replacement Keys: The root level of the document service (the parent datasource) must have unique indexes other than Rec-ID. This may be in the form of a non-RecId Primary Index or a Replacement Key.
·         Related Replacement Keys: Each field within the service which is a RecId-based foreign key must relate to a table that has a replacement key specified.
·         Relationship Direction: When parent-child relationships exist in the underlying query associated with the service, only relationships originating on the child element, and pointing to the parent may be used. For example, in the custCustomerService, the custTable parent data sources holds a foreign key to the dirParty child data source. This pattern is not supported in the Excel Add-in.
·         Query and Service consistency: Document services are based on an underlying query which defines the data contract used in the service at the time that the service is generated. The Excel Add-in uses this query definition to perform read operations when refreshing data into the workbook. Because of this, any overrides to the read method, or extension of the schema beyond what is in the underlying query will not be reflected in the service.
·         View Support: Views may be used within document services to provide an easier to use data model for end users. However, the PrepareForXXXExtended methods must be implemented to properly handle information sent to the service within the views. Views may only be used as the “leaf” level node in the underlying query. For instance if there is a query “Parent, child, grandchild”, then only the grandchild node can be a view.


Friday, February 17, 2012

Ax2012 Get the Dimension values for the Main Account


Get the Dimension Values for the Main Account

static void krishh_dimensionCombValuesforMainAccount(Args _args)
{
    DimensionAttributeValueCombination  dimAttrValueComb;

    DimensionStorage        dimensionStorage;

    DimensionStorageSegment segment;
    int                     segmentCount, segmentIndex;
    int                     hierarchyCount, hierarchyIndex;
    str                     segmentName, segmentDescription;
    SysDim                  segmentValue;

    DimensionHierarchyLevel  dimensionHierarchyLevel;
    RefRecId recordvalue;
    DimensionAttributeValueCombination dimCombination;
    MainAccount  mainAccount;
    ;

   mainAccount=      
 MainAccount::findByMainAccountId('20901',false,LedgerChartOfAccounts::findByName(curext()).RecId);
    recordvalue=DimensionHierarchy::getAccountStructure(mainAccount.RecId);

    select  recid from dimCombination where  dimCombination.MainAccount==mainAccount.RecId
               && dimCombination.AccountStructure==recordvalue;

    dimAttrValueComb = DimensionAttributeValueCombination::find(dimCombination.RecId);
    setPrefix("Breakup for " + dimAttrValueComb.DisplayValue);

    dimensionStorage = DimensionStorage::findById(dimAttrValueComb.RecId);
    if (dimensionStorage == null)
    {
        throw error("No dimension Specified for the Main Account");
    }
    hierarchyCount = dimensionStorage.hierarchyCount();
    for(hierarchyIndex = 1; hierarchyIndex <= hierarchyCount; hierarchyIndex++)
    {
        setPrefix(strFmt("Hierarchy: %1", DimensionHierarchy::find(dimensionStorage.getHierarchyId(hierarchyIndex)).Name));

        segmentCount = dimensionStorage.segmentCountForHierarchy(hierarchyIndex);
        //Loop through segments and display required values
        for (segmentIndex = 1; segmentIndex <= segmentCount; segmentIndex++)
        {
            segment = dimensionStorage.getSegmentForHierarchy(hierarchyIndex, segmentIndex);
            if (segment.parmDimensionAttributeValueId() != 0)
            {
               // Dimension Name
                segmentName = DimensionAttribute::find(DimensionAttributeValue::find(segment.parmDimensionAttributeValueId()).DimensionAttribute).Name;
         
                 // segment value- Dimension Value
                segmentValue        = segment.parmDisplayValue();

                //Description for dimension)
                segmentDescription  = segment.getName();
                info(strFmt("DimensionName:%1: Value:%2,Description: %3", segmentName, segmentValue, segmentDescription));
            }
        }
    }
}

Ax2012 Get Active Dimension Names for Ledger account


Get the active Dimension names for the Ledger order by the Dimension Hierarchy Level.

static void krishh_getActiveFinanicialdimensions(Args _args)
{
    DimensionAttributeSetItem   dimAttrSetItem;
    DimensionAttribute          dimAttr;
    DimensionEnumeration        dimensionSetId;

    DimensionHierarchyLevel     dimHierarchyLevel;
    recId                       chartOfAccountsId;
    LedgerChartOfAccountsStructure  ledgerChartOfAccountsStructure;
    ;
    //Get the record Id (dimension set id) for current ledger to find active dimensions
    dimensionSetId = DimensionCache::getDimensionAttributeSetForLedger();
    chartOfAccountsId = Ledger::find(Ledger::current()).ChartOfAccounts;
    //Find all the active dimensions for current ledger except main account and display them
 
 while select name from dimAttr
            where dimAttr.Type != DimensionAttributeType::MainAccount
        join RecId from dimAttrSetItem
            where dimAttrSetItem.DimensionAttribute == dimAttr.RecId &&
                dimAttrSetItem.DimensionAttributeSet == dimensionSetId
        join RecId from dimHierarchyLevel
                 order by level
                where dimHierarchyLevel.DimensionAttribute == dimAttr.RecId
        exists join ledgerChartOfAccountsStructure
                where ledgerChartOfAccountsStructure.DimensionHierarchy == dimHierarchyLevel.DimensionHierarchy &&
                    ledgerChartOfAccountsStructure.ChartOfAccounts == chartOfAccountsId
    {
        info(dimAttr.Name);
    }

}

Thursday, February 16, 2012

Microsoft Dynamics ERP'S Blog: Dynamics AX Version & Their Build Information

WAQAS BUTT - Microsoft Dynamics ERP'S Blog: Dynamics AX Version & Their Build Information: Dynamics here are the details of Dynamics AX version & their respective build information Dynamics AX 2012 Version ...

Get AX AOS Server running username and Domain


The code must be executed on the server tier.

public static krishh_getAOSUserAndDomain(Args args)
{
    InteropPermission   permission;
    str                 userName;
    str                 userDomain;
    ;
    permission = new InteropPermission(InteropKind::ClrInterop);
    permission.assert();
    userDomain  = System.Environment::get_UserDomainName();
    userName    = System.Environment::get_UserName();
    info(strFmt(@"%1\%2", userDomain, userName));
}

Print Image from AX using X++



The sample prints an image (in this case a TIFF image) to your default printer without prompting first.
Before writing code please add the reference to ax to System.Printing 

static void krishh_PrintImage(Args _args)
{
    System.Printing.PrintServer         localPrintServer    = new     
    System.Printing.LocalPrintServer();
    System.Printing.PrintQueue          printQueue          =   
    System.Printing.LocalPrintServer::GetDefaultPrintQueue();
    System.Diagnostics.Process          printProcess        = new System.Diagnostics.Process();
    System.Diagnostics.ProcessStartInfo processStartInfo;
    str                                 arguments;
    Filename                            fileName            = @'C:\krishhPic.TIF';
    ;

    processStartInfo = printProcess.get_StartInfo();
    processStartInfo.set_Verb("Print Image");
    processStartInfo.set_FileName(@"C:\WINDOWS\System32\rundll32.exe");
    arguments  = @'C:\WINDOWS\System32\shimgvw.dll,ImageView_PrintTo /pt ';
    arguments += @'"';
    arguments += filename;
    arguments += @'" ';
    arguments += @'"';
    arguments += ClrInterop::getAnyTypeForObject(localPrintServer.get_Name()) + @'\' + ClrInterop::getAnyTypeForObject(printQueue.get_Name());
    arguments += @'" ';
    arguments += @'"%3" "%4"';
    processStartInfo.set_Arguments(arguments);
    processStartInfo.set_UseShellExecute(false);
    printProcess.Start();
    printProcess.Close();
}

AX2012 Configure Print Management for SSRS Report


Configure Print Management For the Report in AX2012.

1.     Create the SSRS Report.
2.     Updated based on the requirements from FDD either AutoDesign or Create a prcesion Design and change the name of the precisionDesign to standard name as ’Report’.
3.     Deploy the Report.

When we execute this report we should use the print management functionality for getting the details to print original or copy settings from print management.

In our Example I created the report called as internal Delivery Note from WMSJournal.
This report must be executed from the Journal Form, and while posting the journal if the journal is success then we have to print the original copy of the report.

Step 1-
Creating the Report with the name as InternalDeliveryNote and I created the precision Design and updated that Design name as ’Report’ and Deployed the report.
I have build one query for this report using WMSJournalTable and WMSJournalTrans.
Step 2-
 We have to finalize from which Module we have to print, I have descided to print from invent Module.
     Add the Enum  element in the PrintMgmtNodeType as –InternalDeliveryNote
     Add the Enum Element in the PrintMgmtDocumentType as-InternalDeliveryNote

Added the Code in the following classes

Class -PrintMgmtHierarchy_Invent
Methods-GetNodesImplementation, getParentImplementation

protected List getNodesImplementation()
{
    List supportedNodes = new List(Types::Enum);
    ;

    // Add allowable nodes for this hierarchy
    supportedNodes.addEnd(PrintMgmtNodeType::Invent);
    supportedNodes.addEnd(PrintMgmtNodeType::CustTable);
    supportedNodes.addEnd(PrintMgmtNodeType::InventTransferTable);
    supportedNodes.addEnd(PrintMgmtNodeType::SalesTable);

supportedNodes.addEnd(PrintMgmtNodeType::InternalDeliveryNote);
  

    return supportedNodes;
}

protected PrintMgmtNodeInstance getParentImplementation(PrintMgmtNodeInstance _nodeInstance, PrintMgmtDocumentType _docType)
{
    // added the new swith condition for the report node.

        case PrintMgmtNodeType::InternalDeliveryNote:
            // When no parent is present, return null
            result.parmReferencedTableBuffer(null);
            result.parmNodeDefinition(PrintMgmtNode::construct(PrintMgmtNodeType::InternalDeliveryNote));
            break;
     
    return result;
}

Class –PrintMgmtNode
Method-Construct

public static PrintMgmtNode construct(PrintMgmtNodeType _nodeType)
{
    ;
// add the node to construct the report in which module

    switch (_nodeType)
    {
     
        case PrintMgmtNodeType::InternalDeliveryNote:
            return PrintMgmtNode_Invent::construct();
       
    }

    return null;
}


Class –PrintMgmtDocType
Method-getQueryTableID,getDefaultReportFormat

public int getQueryTableId()
{
    int tableId;

// added switch condition for getting the table id.
    switch (docType)
    {
      
        
        case PrintMgmtDocumentType::InternalDeliveryNote:
            tableId = tableNum(WMSJournalTable);
            break;
     

    }

    return tableId;
}

public PrintMgmtReportFormatName getDefaultReportFormat()
{
    switch (docType)
    {
       
        case PrintMgmtDocumentType::InternalDeliveryNote:
            return ssrsReportStr(InternalDeliveryNote, Report);

    }

    throw Exception::Internal;
}

Class-PrintMgmtNode_Invent
Method-getDocumentTypes

This method will load the print management element in the print management setup.
public List getDocumentTypes()
{
    List docTypes;
    ;

    docTypes = new List(Types::Enum);

    if (isConfigurationkeyEnabled(configurationKeyNum(LogisticsBasic)))
    {
        docTypes.addEnd(PrintMgmtDocumentType::InventPickList);

     
        docTypes.addEnd(PrintMgmtDocumentType::InternalDeliveryNote);
     
    }
    return docTypes;
}


Execute the Report using printmanagement setup we have to write the class which inherits SRSPrintMgmtController
So Our class declarations will be look like this
class InternalDeliveryNoteController extends SrsPrintMgmtController
{
    #define.ReportName('InternalDeliveryNote.Report')
    InventDimParm                               inventDimVisible;
    WMSPickingRoute                             wmsPickingRoute;
    PrintCopyOriginal                           printCopyOriginal;
    WMSJournalTable                             wmsJournalTable;
    WMSJournalTrans                             wmsJournalTrans;
}

public static void main(Args _args)
{
    InternalDeliveryNoteController controller = new InternalDeliveryNoteController();
    controller.parmReportName(#ReportName);
    controller.parmArgs(_args);
    controller.parmDialogCaption(_args.parmEnum() == PrintCopyOriginal::Original ? "Internal Delivery Note" : strFmt("%1 - %2","Original", "Copy"));
    controller.parmPrintType(_args.parmEnum());
    controller.parmShowDialog(false);


    controller.startOperation();
}

protected void setRanges(Query _query)
{
    QueryBuildRange         queryBuildRange;
    FormDataSource          formDataSource;
    Common                  common;
    Range                   journalRange, lineRange;

    if (!this.parmArgs().record().RecId)
    {
        throw error(strFmt("@SYS22338",funcName()));
    }

    if (this.parmArgs().dataset() == tableNum(WMSJournalTable) || this.parmArgs().dataset() == tableNum(WMSJournalTrans))
    {
        if (_query)
        {
            formDataSource  = this.parmArgs().record().dataSource();

            if(formDataSource && formDataSource.anyMarked())
            {
                common          = formDataSource.getFirst(1);

                while(common.RecId)
                {
                    if (common.TableId == tableNum(WMSJournalTable))
                    {
                        journalRange    += common.(fieldNum(WMSJournalTable, JournalId)) + ",";
                        wmsJournalTable=common;
                    }
                    else
                    {
                        journalRange    = common.(fieldNum(WMSJournalTrans, JournalId)) + ",";
                        lineRange       += strFmt("%1,", common.(fieldNum(WMSJournalTrans, LineNum)));
                        WMSJournalTrans=common;
                    }

                    common          = formDataSource.getNext();
                }
            }
            else
            {
                common          = this.parmArgs().record();

                if (common.TableId == tableNum(WMSJournalTable))
                {
                    journalRange    = common.(fieldNum(WMSJournalTable, JournalId));
                        wmsJournalTable=common;
                }
                else
                {
                    journalRange    = common.(fieldNum(WMSJournalTrans, JournalId));
                    lineRange       = strFmt("%1,", common.(fieldNum(WMSJournalTrans, LineNum)));
                    WMSJournalTrans=common;
                }
            }

            queryBuildRange = SysQuery::findOrCreateRange(_query.dataSourceTable(tableNum(WMSJournalTrans)), fieldNum(WMSJournalTrans, JournalId));
            queryBuildRange.value(journalRange);

            if (lineRange)
            {
                queryBuildRange = SysQuery::findOrCreateRange(_query.dataSourceTable(tableNum(WMSJournalTrans)), fieldNum(WMSJournalTrans , LineNum));
                queryBuildRange.value(lineRange);
            }
            else
                _query.dataSourceTable(tableNum(WMSJournalTrans)).clearRange(fieldNum(WMSJournalTrans , LineNum));
        }
    }
    else
    {
        throw error(strFmt("@SYS23396",funcName()));
    }

}

Override the method which sets our ranges for query  to the report

protected void prePromptModifyContract()
{
    this.setRanges(this.parmReportContract().parmQueryContracts().lookup(this.getFirstQueryContractKey()));
}

public PrintCopyOriginal parmPrintType(PrintCopyOriginal _parmPrintType = PrintCopyOriginal)
{
    PrintCopyOriginal = _parmPrintType;
    return PrintCopyOriginal;
}

public SRSPrintDestinationSettings parmDefaultCopyPrintJobSettings(SRSPrintDestinationSettings _printSettings = printMgmtReportRun.parmDefaultCopyPrintJobSettings())
{
    return printMgmtReportRun.parmDefaultCopyPrintJobSettings(_printSettings);
}

public SRSPrintDestinationSettings parmDefaultOriginalPrintJobSettings(SRSPrintDestinationSettings _printSettings= printMgmtReportRun.parmDefaultOriginalPrintJobSettings())
{
    return printMgmtReportRun.parmDefaultOriginalPrintJobSettings(_printSettings);
}

public void loadPrintSettings(Common _jourTable, Common _transTable, str _languageId, str _documentKeyValue = '')
{
    boolean isValidReference(Common _referencedTableBuffer)
    {
        PrintMgmtNodeInstance nodeInstance = new PrintMgmtNodeInstance();

        nodeInstance.parmNodeDefinition(PrintMgmtNode::construct(PrintMgmtNodeType::InternalDeliveryNote));
        nodeInstance.parmReferencedTableBuffer(_referencedTableBuffer);

        return nodeInstance.isValidReference();
    }

    void setSettingDetail(PrintMgmtDocInstanceType _type, SRSPrintDestinationSettings _defaultSettings)
    {
        PrintMgmtPrintSettingDetail printSettingDetail = new PrintMgmtPrintSettingDetail();

        printSettingDetail.parmReportFormatName(PrintMgmtReportFormat::findSystem(PrintMgmtDocumentType::InternalDeliveryNote).Name);

        printSettingDetail.parmType(_type);

        printSettingDetail.parmInstanceName(enum2str(_type));

        // Since this will be reported to the screen, one copy is the only thing that makes sense
       // printSettingDetail.parmNumberOfCopies(1);

        printSettingDetail.parmPrintJobSettings(_defaultSettings);
        printSettingDetail.parmNumberOfCopies(_defaultSettings.numberOfCopies());
        printMgmtReportRun.loadSettingDetail(printSettingDetail, _documentKeyValue);
    }

    if (this.parmPrintType() == PrintCopyOriginal::OriginalPrint && isValidReference(_transTable))
    {
        // Print an original
        printMgmtReportRun.load(_jourTable, _transTable, _languageId, _documentKeyValue);
    }
    else if (this.parmPrintType() == PrintCopyOriginal::Copy)
    {
        // Print a copy
        setSettingDetail(PrintMgmtDocInstanceType::Copy, this.parmDefaultCopyPrintJobSettings());
    }
    else
    {
        // Print an original.  We also default to print one original when we are trying to
        // print using Print Mgmt information, but don't have a valid table reference.
        // This covers the reprint case where the original transaction record may not be present.
        setSettingDetail(PrintMgmtDocInstanceType::Original, this.parmDefaultOriginalPrintJobSettings());
    }

    if (!printMgmtReportRun.more())
    {
        checkFailed("@SYS78951");
    }
}


This method is used to get the printmgmt settings from the table printmgmtsettings that we define in the pringmangement setup.

private void getPrintSettings(PrintMgmtDocInstanceType _printMgmtDocInstanceType =PrintMgmtDocInstanceType::Copy)
{
    PrintMgmtSettings  printMgmtSettings;
    PrintMgmtDocInstance printMgmtDocInstance;
    PrintMgmtReportFormat printMgmtReportFormat;
    SRSPrintDestinationSettings srsPrintDestinationSettings;

    select RecId from printMgmtReportFormat where printMgmtReportFormat.Name==this.parmReportName()
    join DocumentType,PrintType from printMgmtDocInstance where printMgmtDocInstance.DocumentType==PrintMgmtDocumentType::InternalDeliveryNote
        && printMgmtDocInstance.PrintType==_printMgmtDocInstanceType
    Join PrintJobSettings,NumberOfCopies,ParentId from printMgmtSettings where printMgmtSettings.ReportFormat==printMgmtReportFormat.RecId
    && printMgmtSettings.ParentId==printMgmtDocInstance.RecId;

    if(_printMgmtDocInstanceType==PrintMgmtDocInstanceType::Copy)
    {
        srsPrintDestinationSettings=new SRSPrintDestinationSettings(printMgmtSettings.PrintJobSettings);
        srsPrintDestinationSettings.numberOfCopies(printMgmtSettings.NumberOfCopies);
        this.parmDefaultCopyPrintJobSettings(srsPrintDestinationSettings);
    }
    else
    {
        srsPrintDestinationSettings=new SRSPrintDestinationSettings(printMgmtSettings.PrintJobSettings);
        srsPrintDestinationSettings.numberOfCopies(printMgmtSettings.NumberOfCopies);
        this.parmDefaultOriginalPrintJobSettings(srsPrintDestinationSettings);
    }
}


Override the runprintmgmt function to call the report with the settings that we used in the above functions.
protected void runPrintMgmt()
{
    printMgmtReportRun=PrintMgmtReportRun::construct(PrintMgmtHierarchyType::Invent,PrintMgmtNodeType::InternalDeliveryNote,PrintMgmtDocumentType::InternalDeliveryNote);
    printMgmtReportRun.parmReportRunController(this);

    if (this.parmPrintType() == PrintCopyOriginal::Copy)
    {
        //// Print a copy
        this.getPrintSettings();
    }
    else
    {
        //// Print an original.  We also default to print one original when we are trying to
        //// print using Print Mgmt information, but don't have a valid table reference.
        //// This covers the reprint case where the original transaction record may not be present.
        this.getPrintSettings(PrintMgmtDocInstanceType::Original);
        //printMgmtReportRun.loadSettingDetail(this.setSettingDetail(PrintMgmtDocInstanceType::Original, printMgmtReportRun.parmDefaultOriginalPrintJobSettings()));
    }

    this.loadPrintSettings(wmsJournalTable,wmsJournalTrans,CompanyInfo::languageId());
    this.outputReports();
}

After finishing the development we have to set the values for the printmanagement.
Goto- inventorymanagement parameters-Printmanagement-click on printmanagement button.
Then the printmgmtuiMain form will loads with the nodes that we define in the development. As follows.

Then click on internaldelivery note and right click you will get new and click ok.it will create original, create again new it will create copy for that document as follows

and click on close button.Create one menuitem  for output section as follows.