Sunday, June 23, 2019

How to send multiple Free Text Invoices for direct printing to printer using x++ D365 FO

One of the typical requirements from most of the customers is to directly send multiple Posted Customer Invoices to the Network Printer so that we can save ourselves from the pain of Exporting to PDF files manually and printing them later.


Before we write the code to achieve this functionality. We need to follow few steps which are mentioned below :-


1) Go to Organization Administration --> Setup --> Network Printers --> download Microsoft

Dynamics Routing Agent (You can find this in action pane)

2) Once downloaded and installed open DRA

3) Go to settings and enter the D365 URL and Azure AD tenant :-
 
          D365 URL :- https://abc-aos.ax.dynamics.com

          Azure AD Tenant :- abcxyz.onmicrosoft.com

4) Do not select the option Run as Windows Service

5) Close the application and reopen it

6) Enter the credentials for the Azure AD Tenant

7)Click Printers and it will show all the printers available on your specific network

8) Mark your required printers and click Register


Once done write the below code in an event handler :-


 [FormControlEventHandler(formControlStr(CustFreeInvoice, BulkInvoicePrint), FormControlEventType::Clicked)]
    public static void BulkInvoicePrint_OnClicked(FormControl sender, FormControlEventArgs e)
    {
        int                                             loop;
        FormDataSource                      fds;
        MultiSelectionHelper               selectionHelper = MultiSelectionHelper::construct();
        Set                                             selectedRecords = new Set(Types::Record);
        CustPrintOutInvoice                 custPrintOutInvoice;
        NoYes                                       usePrintManagement;
        RecordSortedList                      recordSortedList;
        CustInvoiceTable                      currentCustInvoiceTable;
        SalesInvoiceJournalPrint          salesInvoiceJournalPrint;
        CustInvoiceJour                        custInvoiceJour;
        CustInvoiceTable                      currCustInvoiceTable;
        SRSPrintDestinationSettings    srsPrintDestinationSettings;
        RecordSortedList                      custInvoiceJourList;
        RecordSortedList                      rsl;
        SrsReportRunController              controller = new SrsReportRunController();
        FreeTextInvoiceContract  rdpContract = new FreeTextInvoiceContract();
        SysCorpNetPrinters                      netPrinters;
     

        fds = sender.formRun().dataSource('CustInvoiceTable');

        rsl = FreeTextInvoiceEventHandler::getSelectedRecords(fds);

        Args args = new Args();

        select firstonly netPrinters where
        netPrinters.Active == NoYesCombo::Yes &&
            netPrinters.EnableSalesInvoiceDocumentPrint==NoYes::Yes;

        custInvoiceJourList = new RecordSortedList(tableNum(CustInvoiceJour));
        custInvoiceJourList.sortOrder(fieldNum(CustInvoiceJour, RecId));

        for (loop = rsl.len(); loop > 0; loop--)
        {
            rsl.next(currentCustInvoiceTable);
            custInvoiceJour = currentCustInvoiceTable.custInvoiceJour();
            if (custInvoiceJour.RecId)
            {
                selectedRecords.add(custInvoiceJour);
           
                controller.parmReportName(ssrsReportStr(FreeTextInvoiceNew, Report));
             
                controller.parmExecutionMode(SysOperationExecutionMode::Synchronous);

                controller.parmShowDialog(false);

                rdpContract.parmRefRecid(currentCustInvoiceTable.RecId);
                rdpContract.parmInvoiceId(currentCustInvoiceTable.InvoiceId);

                controller.parmReportContract().parmRdpContract(rdpContract);

                srsPrintDestinationSettings = controller.parmReportContract().parmPrintSettings();
             
                srsPrintDestinationSettings.fromPage(1);
                srsPrintDestinationSettings.toPage(1);
                srsPrintDestinationSettings.landscape(false);
                srsPrintDestinationSettings.printerName(netPrinters.PrinterName);
                srsPrintDestinationSettings.printMediumType(SRSPrintMediumType::Printer);
                srsPrintDestinationSettings.numberOfCopies(1);
                srsPrintDestinationSettings.collate(false);
                controller.startOperation();
             
                stInvoiceJourList.ins(custInvoiceJour);
            }
         
        }

     



    }

 

     public static  RecordSortedList getSelectedRecords(FormDataSource fds1)
    {
        RecordSortedList recordSortedList;
        CustInvoiceTable currentCustInvoiceTable;

        recordSortedList = new RecordSortedList(tableNum(CustInvoiceTable));
        recordSortedList.sortOrder(fieldNum(CustInvoiceTable,RecId));

        currentCustInvoiceTable = Global::getFirstSelection(fds1);

        while (currentCustInvoiceTable)
        {
            recordSortedList.ins(currentCustInvoiceTable);
            currentCustInvoiceTable = fds1.getNext() as CustInvoiceTable;
        }

        return recordSortedList;
    }

How to post multiple Free Text Invoices using x++ D365 FO

These days one of the most common requirements is to post multiple Customer Invoices in a single click.


Here is an example :-

[FormControlEventHandler(formControlStr(CustFreeInvoice, BulkPost), FormControlEventType::Clicked)]
public static void BulkPost_OnClicked(FormControl sender, FormControlEventArgs e)
{

    FormDataSource                fds;
    MultiSelectionHelper         selectionHelper = MultiSelectionHelper::construct();
    Set                                       selectedRecords = new Set(Types::Record);
    CustInvoiceTable                custInvoiceTable;
    CustPostInvoice                  custPostInvoice;
     
        fds = sender.formRun().dataSource('CustInvoiceTable');

        custInvoiceTable = fds.cursor();

        selectionHelper.parmDataSource(fds);
        custInvoiceTable  = selectionHelper.getFirst();

        if (custInvoiceTable.RecId)
        {
            while (custInvoiceTable)
            {
                selectedRecords.add(custInvoiceTable);
                custPostInvoice = new CustPostInvoice(custInvoiceTable);
                custPostInvoice.run();
                custInvoiceTable = selectionHelper.getNext();
            }
        }

        fds.research();
        fds.reread();
        fds.refresh();

        Box::info('Invoice Posting Completed Successfully');
}

How to create a Dimension Value using x++ D365 FO

There are lot of tables holding values for Financial Dimensions such as DimensionAttributeValue and DimensionAttributeValueCombination but in case if we can't find the values in these above tables then we have another table known as DimensionFinancialTag through which we can get values as well as we can create new dimensions as well.


Here is an example mentioned below :-

        
 DimDetails                                          dimensiondetails;
 DimensionAttribute                             dimAttr;
 DimensionAttributeValue                    dimAttrValue;
 DimensionDefault                                result;
 DimensionFinancialTag                       dimFinTag , dimFinTagval;
 RecId                                                    dimFinancialCategoryRecid;
        
DimensionAttributeValueSetStorage   valueSetStorage = new 

DimensionAttributeValueSetStorage();

        try
        {
        dimAttr = DimensionAttribute::findByName('ABC');
        dimFinancialCategoryRecid = dimAttr.financialTagCategory();
        while select dimensiondetails where dimensiondetails.UpdateFlag==0
        {
            select dimFinTag where
                   dimFinTag.FinancialTagCategory == dimFinancialCategoryRecid &&
                   dimFinTag.Value == dimensiondetails.AssetCode;

            if(!dimFinTag.RecId)
            {
                dimFinTagval.Value = dimensiondetails.AssetCode;
                dimFinTagval.Description = dimensiondetails.AssetDescription;
                dimFinTagval.FinancialTagCategory = dimFinancialCategoryRecid;
                dimFinTagval.insert();
                
            }

            
        }

        }

        catch(Exception::Error)
        {
            ttsAbort;
            throw Exception::Error;
        }

Sunday, March 17, 2019

How to open a Web Page using x++ D365 FO

Hi Folks ,

All we need to do to achieve this is follow these simple steps :-


1) Create a Runnable Class

2) Write the following logic in the class :-

               class ABC
              {
                      public static void main(Args _args)
                      {
                            Browser browser = new Browser();
                            browser.navigate('www.google.com', true, false);
                       }

                }

         Same logic we can use in event handlers or on clicked event of a button.


         Happy Coding !!!!

Tuesday, December 11, 2018

How to create a Customer Payment Journal using x++ in D365 FO

Hi guys ,


This is the most common requirement these days that the customer wants to create a payment journal  automatically on triggering of certain events in D365 Fin Ops.

In the below example we are taking the values from a data entity and create payment journal accordingly for each record of this entity :-

       #OCCRetryCount
        int64                                                    dim;
        CustInvoiceTable                                custInvoiceTable_loc;
        Counter                                               progressCount,progressTotal;
        Ledgerjournalname                             ledgerjournalname;
        LedgerjournalTable                             LedgerjournalTable;
        LedgerjournalTrans                             LedgerjournalTrans;
        CustTable                                            custtable_loc;
        NumberSeq                                         numberSeq;
        CustParameters                                   custParametersExt;
        CustInvoiceTrans                                custInvoiceTrans;
        CustInvoiceJour                                  custInvoiceJour;
        PaymentJournalDetailsEntity             paymentjour , paymentjourupdate;
        SalesTable                                          salestbl;
        DimensionAttribute                           dimBusinessUnitAttribute , dimProfitCenterAttribute ;
        DimensionAttributeValue                  dimAttributeBusinessUnitValue,                                                                                                               dimAttributeProfitCenterValue;
        DimensionDefault                              defaultDimension;
        DimensionAttributeValueSetItem      dimensionAttributeValueSetItem;
        DimensionDynamicAccount              ledgerDim;
        Currency                                             currencydet;
        DimensionAttributeValueSetStorage  dimStorage = new DimensionAttributeValueSetStorage();
     
     

        try
        {
         
            select * from custParametersExt;

         
            if(custParametersExt.EnablePaymentJournalIntegration==NoYes::Yes)
            {

                while select paymentjour where paymentjour.UpdateFlag==0
                {
                    custtable_loc   = CustTable::find(paymentjour.CustomerAccount);

                    select currencydet where currencydet.CurrencyCode==paymentjour.Currency;

               
                    select dimensionAttributeValueSetItem where                                                                                                    dimensionAttributeValueSetItem.DisplayValue==paymentjour.BusinessUnit;

                    select dimensionAttributeValueSetItem1 where                                                                                                  dimensionAttributeValueSetItem1.DisplayValue==paymentjour.ProfitCenter;

                    if(custtable_loc)
                    {
                        if(currencydet)
                        {
                            if(dimensionAttributeValueSetItem)
                            {
                                    ledgerDim =                                                                                                                                                   LedgerDynamicAccountHelper::getDynamicAccountFromAccountNumber
                                         (paymentjour.CustomerAccount,LedgerJournalACType::Cust);
                 
                                    select custInvoiceTrans where                                                                                                                            custInvoiceTrans.InvoiceId==custInvoiceJour.InvoiceId;

                                    select ledgerjournalname where ledgerjournalname.JournalName ==                                                                custParametersExt.PaymentJournalName;

                                    ttsBegin;
                                    LedgerjournalTable.JournalName =  custParametersExt.PaymentJournalName;
                                    LedgerjournalTable.initFromLedgerJournalName();
                                    LedgerjournalTable.JournalNum  =                                                                                                                             JournalTableData::newTable(LedgerjournalTable).nextJournalId();

                                    if(paymentjour.InvoiceId!="" && paymentjour.MethodofPayment!="")
                                    {
                                        LedgerjournalTable.Name        =  paymentjour.InvoiceId + " - " +                                                                                                                           paymentjour.MethodofPayment;
                                    }
                                    if(paymentjour.InvoiceId=="" && paymentjour.MethodofPayment=="")
                                    {
                                        LedgerjournalTable.Name = paymentjour.SalesID;
                                    }
                                    if(paymentjour.InvoiceId!="" && paymentjour.MethodofPayment=="")
                                    {
                                        LedgerjournalTable.Name = paymentjour.InvoiceId + " - " +                                                                                                                                                 paymentjour.SalesID;
                                    }
                                    if(paymentjour.InvoiceId=="" && paymentjour.MethodofPayment!="")
                                    {
                                        LedgerjournalTable.Name = paymentjour.SalesID + " - " +                                                                                                                                   paymentjour.MethodofPayment;
                                    }
                                    LedgerjournalTable.insert();

         
                                    if(ledgerjournalname)
                                    {
             
                         
                                        numberSeq =  NumberSeq::newGetVoucherFromId((
                                                                                     ledgerjournalname.NumberSequenceTable));
                                        LedgerjournalTrans.Voucher          =   numberSeq.voucher();
                                        LedgerjournalTrans.JournalNum    =   LedgerjournalTable.JournalNum;         
                                        LedgerjournalTrans.AccountType  =   LedgerJournalACType::Cust;
                                        LedgerjournalTrans.Company        =   curext();
                                        LedgerjournalTrans.parmAccount(custtable_loc.AccountNum,
                                                                                                 LedgerjournalTrans.AccountType);
                                        LedgerjournalTrans.CurrencyCode =   paymentjour.Currency;
                                        LedgerjournalTrans.TransDate        =   paymentjour.TransDate;
                                        LedgerjournalTrans.Txt                   =   LedgerjournalTable.Name;
   
                               
                                        LedgerjournalTrans.DefaultDimension  =  custtable_loc.DefaultDimension;
                         
                                        defaultDimension  = LedgerjournalTrans.DefaultDimension;
                                        dimStorage  = DimensionAttributeValueSetStorage::find(defaultDimension);
                                                                                                                                                                                                       dimBusinessUnitAttribute = DimensionAttribute::findByName('BusinessUnit');
                                   dimProfitCenterAttribute   = DimensionAttribute::findByName('CostCenter');
                               
                                   dimAttributeBusinessUnitValue=                                                                                                                                DimensionAttributeValue::findByDimensionAttributeAndValue
                                                      (dimBusinessUnitAttribute,paymentjour.BusinessUnit , true, true);
                                    dimAttributeProfitCenterValue   =                                                                                                                              DimensionAttributeValue::findByDimensionAttributeAndValue
                                                      (dimProfitCenterAttribute,paymentjour.ProfitCenter , true, true);

                                        dimStorage.addItem(dimAttributeBusinessUnitValue);
                                        dimStorage.addItem(dimAttributeProfitCenterValue);
                                        LedgerjournalTrans.DefaultDimension = dimStorage.save();
                                     
                                        LedgerjournalTrans.TransactionType          =   LedgerTransType::Payment;
                                        LedgerjournalTrans.LedgerDimension          =   ledgerDim;
                                        LedgerjournalTrans.AmountCurCredit          =   paymentjour.Amount;
   
                                        LedgerjournalTrans.insert();
                                    }

                                    ttscommit;

                                    if(LedgerjournalTable && LedgerjournalTrans)
                                    {
                                        ttsbegin;

                                        select forupdate paymentjourupdate where                                                                                                          paymentjourupdate.RecId==paymentjour.RecId;
                                        paymentjourupdate.UpdateFlag=1;
                                        paymentjourupdate.update();

                                        ttscommit;
                                    }
                             
                            }
                        }
                    }

                     
                 
             
                }
         
         
            }
         
         
        }
        catch(Exception::Error)
        {
            throw error('Payment Journal Creation Failed');
        }
        catch(Exception::Deadlock)
        {
            retry;
        }
        catch(Exception::UpdateConflict)
        {
            if(appl.ttsLevel()==0)
            {
                if(xSession::currentRetryCount()>=#RetryNum)
                {
                    throw exception::UpdateConflictNotRecovered;
                }
                else
                {
                    retry;
                }
            }
            else
            {
                throw exception::UpdateConflict;
            }
        }

Monday, October 1, 2018

How to Flush Usage Data and Cache in Dynamics 365 FO



Most of the times we need to clear cache and usage data in order to avoid any kind of refresh issues.


In Dynamics 365 FO we can do it through running a simple url in the browser :-


https://abc.sandbox.ax.dynamics.com/?cmp=dat&mi=SysClassRunner&cls=SysFlushData




Happy Daxing !!!!

Wednesday, August 1, 2018

How to Consume JSON Web API using GET Method in Dynamics 365 FO


One very basic requirement now a days is the consumption of data of  any other Web Based Application in Dynamics 365 Finance and Operations.

Similary we can use the code below for consumption of a JSON based Web API used to expose data from Microsoft Dynamics CRM but instead it can be used for any other kind of Web Application hosted as a Web API on Azure.



        int                                                      find;
        str                                                      url,aosUri,activeDirectoryTenant;
        str                                                      activeDirectoryClientAppId;
        str                                                      activeDirectoryClientAppSecret;
        str                                                      postData,activeDirectoryResource,
        str                                                      aadClientAppSecret,oAuthHeader;
        str                                                      returnValue,jsonString,jsondszstr;
        System.Net.HttpWebRequest           request;
        System.Net.HttpWebResponse         response;
        System.Byte[]                                   byteArray;
        System.IO.Stream                             dataStream;
        System.IO.StreamReader                 streamRead;
        System.IO.StreamWriter                  streamWrite;
        System.Net.ServicePoint                  servicePoint;
        System.Net.ServicePointManager    servicePointmgr;
        System.Net.HttpVersion                   version;
        CLRObject                                        clrObj;
        Newtonsoft.Json.JsonReader            reader;
        System.Text.Encoding                      utf8;
        Counter                                             countCounter;
        Object                                               obj;
        Map                                                  data;

        System.Net.WebHeaderCollection headers = new System.Net.WebHeaderCollection();
   

        new InteropPermission(InteropKind::ClrInterop).assert();

     

        headers = new System.Net.WebHeaderCollection();
        url = "https:///abcd1234.crm4.dynamics.com/api/data/v8.1/detail";
     
        clrObj = System.Net.WebRequest::Create(url);
     
     
        request = clrObj;
        request.set_Method("GET");
        request.set_KeepAlive(true);
     
        request.set_ContentType("application/json");

        aosUri = "https://login.windows.net/xyz1234/oauth2/authorize?";

        activeDirectoryTenant = "https://login.microsoftonline.com/xyz1234/oauth2/token";

        activeDirectoryClientAppId = "abcd3-xyz456-7yd7-09a1-09865ec1d3";

        activeDirectoryResource = "https://abcd1234.crm4.dynamics.com";

        Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext authenticationContext =      new           Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext(activeDirectoryTenant);

     

        var userCredential = new  Microsoft.IdentityModel.Clients.ActiveDirectory.UserCredential("admin@xyz.onmicrosoft.com", "abcd@1234");

        Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationResult authenticationResult =
            authenticationContext.AcquireTokenAsync(activeDirectoryResource, activeDirectoryClientAppId, userCredential).Result;

     
        headers.Add("Authorization", authenticationResult.CreateAuthorizationHeader());
        request.set_Headers(headers);
     
     

        servicePoint = request.get_ServicePoint();

        System.Net.ServicePointManager::set_Expect100Continue(false);

        System.Net.ServicePointManager::set_SecurityProtocol(System.Net.SecurityProtocolType::Tls12);

     

        response = request.GetResponse();

     
        dataStream = response.GetResponseStream();


        streamRead = new System.IO.StreamReader(dataStream);

        jsonString = streamRead.ReadToEnd();

        info(strFmt("%1",jsonString));

        dataStream.Close();

        response.Close();
   

Demystifying the SysOperation Framework in D365 F&O: Building Scalable and Maintainable Batch Jobs

 If you've been developing in Dynamics 365 Finance and Operations for a while, chances are you've either worked with or heard about ...