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();
   

Tuesday, July 24, 2018

How to consume JSON Service(WebAPI) using POST method in Dynamics 365 FO


With the increasing scope of Microsoft Dynamics 365 Finance and Operations in the ERP Industry an efficient requirement is to perform its integration  with other applications.

One basic example is to perform an Integration with a JSON REST Service through a published WebAPI.

In the below example I have done the integration with Dynamics CRM where I am sending some values to CRM from Operations :-

The Code goes like this :-


    int                             find;
    real                           inventOnHandQtyval;
    str                             url,aosUri,activeDirectoryTenant;
    str                             activeDirectoryClientAppId;
    str                             activeDirectoryClientAppSecret,json;
    str                             postData,activeDirectoryResource;
    str                             aadClientAppSecret,oAuthHeader;
    str                             prdGUIDCode,prodnum;
    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;
    System.Web.Script.Serialization.JavaScriptSerializer jsonSerializer;
    CLRObject                       clrObj;
    Newtonsoft.Json.JsonReader      reader;
    Newtonsoft.Json.Linq.JObject    prod;

    System.Text.Encoding            utf8;
    System.Exception                ex;
    Counter                         countCounter;
    Object                          obj;
    Map                             data;
    EcoResProduct                   ecoresproductfetch;
    EcoResProductTranslation        ecoresproductTranslation;
    InventTableModule               inventTableModule;




    try
    {
        InventTable     inventtable = sender as InventTable;

        System.Net.WebHeaderCollection  headers = new System.Net.WebHeaderCollection();
        var jsonSerializerobj = new  System.Web.Script.Serialization.JavaScriptSerializer();
        prod = new Newtonsoft.Json.Linq.JObject();
        inventOnHandQtyval = InventOnhand::newItemId(inventtable.ItemId).availPhysical();
        select inventTableModule where inventTableModule.ItemId==inventtable.ItemId;
        prod.Add("name",inventtable.itemName());
        prod.Add("productnumber",inventtable.ItemId);
        prod.Add("defaultuomscheduleid@odata.bind","/uomschedules(7F6F7338-1D80-4E90-9110-A70897C73834)");
        prod.Add("defaultuomid@odata.bind","/uoms(68A2E342-E1CA-4CC2-B430-C05057BCE7BC)");
        prod.Add("currentcost",0.00);
        prod.Add("description",inventtable.itemName());
        prod.Add("msdyn_fieldserviceproducttype",690970000);


        json=Newtonsoft.Json.JsonConvert::SerializeObject(prod);

        System.IO.MemoryStream mem = new System.IO.MemoryStream();



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



        headers = new System.Net.WebHeaderCollection();

        url = "https://abc.crm4.dynamics.com/api/data/v8.1/details";

        clrObj = System.Net.WebRequest::Create(url);

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

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

        activeDirectoryClientAppId = "xyz124";



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

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



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

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


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

        headers.Add("Prefer", "return=representation");
        request = clrObj;

        request.Headers=headers;

        utf8 = System.Text.Encoding::get_UTF8();
        byteArray = utf8.GetBytes(json);
        request.set_Method("POST");
        request.set_KeepAlive(true);

        request.ContentType="application/json";

        request.set_ContentLength(byteArray.Length);







        servicePoint = request.get_ServicePoint();

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

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



        dataStream = request.GetRequestStream();

        dataStream.Write(byteArray, 0, byteArray.get_Length());

        response = request.GetResponse();



            dataStream = response.GetResponseStream();


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

            jsonString = streamRead.ReadToEnd();



            data=RetailCommonWebAPI::getMapFromJsonString(jsonString);

            prdGUIDCode = data.lookup("productid");

            prodnum = data.lookup("productnumber");         

    }

    catch(Exception::CLRError)
    {
        ex = CLRInterop::getLastException().GetBaseException();
        error(ex.get_Message());
    }





    dataStream.Close();

    response.Close();

Monday, April 30, 2018

How to configure Visual Studio for development in Dynamics 365 FO

A very important step is to configure Visual Studio for the development purpose. A properly configured IDE can enhance your development skills avoiding any time consuming prospects.


After you have downloaded the VM from Life Cycle Services :-


1) Mount the VM on either HyperV or VirtualBox whichever suits your requirement.

2) Login into the machine by using the standard password :- pass@word1

3) On the desktop you will find an icon of Admin Provisioning Tool such as below :-

4) Open this tool and enter your Office 365 subscription address and click Submit :-



5) Once done go to All Programs-->Visual Studio 2015-->Right click-->Run as Administrator











6) Once Visual Studio opens go to Dynamics 365 Menu and select Options then select Dynamics 365  Category


















7) As we can see that as per the standards of Microsoft Best Practice all the options are already enabled

8) Now only we have enable some options for the smooth and well categorized functioning of our future projects. So under Dynamics 365 section go to Projects subcategory.


9) As you can see that we have selected the first and last option its not necessary to select these options before starting your development but if we do it will make our job whole lot easier and organized and selecting the Synchronize database on build for newly created project will help us to avoid extra efforts for Full Database Synchronization every time we create any Data Dictionary Object such as Extended Data Types or Tables.


10) That's it now we are ready to get started with Dynamics 365 Finance and Operations customizations.

Tuesday, April 24, 2018

How to Post Sales Order Invoice through X++ in Dynamics 365 FO


A very common requirement these days is to automate the Invoice Posting for Sales Orders.


Follow the below mentioned steps :-


Step 1) Add a new Runnable class in your Project














Step 2) Write the following code :-


 SalesFormLetter         letter      = SalesFormLetter::construct(DocumentStatus::Invoice);
 SalesTable                   salestbl;

salestbl=SalesTable::find('000814');
 
 
letter.update(salestbl,SystemDateGet(),SalesUpdate::All,AccountOrder::None,false,true);

 info('Success');


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 ...