Friday, 8 March 2024

How to make one of the Financial dimension value as read only using x++

On Form initializes

    public void init()

    {

        DimensionAttribute              dimAttr;

        DimensionAttributeSetStorage    dimStorage;

        DimensionEnumeration            editableDimensionSet;

 

        next init();

 

        dimStorage = new DimensionAttributeSetStorage();

   

        while select HashKey, RecId from dimAttr

            where dimAttr.Type != DimensionAttributeType::DynamicAccount

            &&    dimAttr.Type != DimensionAttributeType::MainAccount

            &&    dimAttr.Name != "Business Unit"

        {

            dimStorage.addItem(dimAttr.RecId, dimAttr.HashKey, NoYes::Yes);

        }

 

        editableDimensionSet = dimStorage.save();

 

        //Make Business unit Read only

        if(editableDimensionSet)

        {

            DimensionEntryControlTable.parmEditableDimensionSet(editableDimensionSet);

            DimensionEntryControlTable.allowEdit(true);

        }

    }

 








Note:

DimensionEntryControlTable = Dimension Entry control

Thursday, 4 May 2023

Download multiple files as Zip from blob using x++ code

 Download file from blob

    public static System.IO.Stream   downloadFromBlob(ENCDocumentType _documentType, Filename _fileName)

    {

        Filename folder = ENCBlobUtil::getBlobFolderName(_documentType);

        try

        {

            CloudStorageAccount  cloudStorageAccount  = CloudStorageAccount::Parse(AzureStorageString); 

            CloudBlobClient cloudBlobClient = cloudStorageAccount.CreateCloudBlobClient();

            CloudBlobContainer cloudBlobContainer  = cloudBlobClient.GetContainerReference(folder);

            CloudBlockBlob  cloudBlockBlob = cloudBlobContainer.GetBlockBlobReference(_fileName);       

            System.IO.Stream stream = new System.IO.MemoryStream();

            cloudBlockBlob.DownloadToStream(stream, null, null, null);

            return stream;

        }

        catch

        {

            throw error(strFmt("Cannot download file to blob"));

        }

    }


    private void downloadAsZip()

    {  

        MultiSelectionHelper                helper;

        DocIntegrationHistoryTable          record;

        str                                 zipFileName;

        str                                 dateTimestamp;

 

        helper              = MultiSelectionHelper::construct();

        helper.parmDatasource(DocIntegrationHistoryTable_DS);

        record              = helper.getFirst();

        dateTimestamp =  today();       

        zipFileName = curUserId()+"_"+ dateTimestamp + ".zip";

        using(System.IO.MemoryStream zipStream  = new System.IO.MemoryStream())

        {

            using (System.IO.Compression.ZipArchive zipArchive = new System.IO.Compression.ZipArchive(zipStream, System.IO.Compression.ZipArchiveMode::Create, true))

            {

                while (record)

                {

                    // Creates the file entry in the zip folder.

                    System.IO.Compression.ZipArchiveEntry fileEntry = zipArchive.CreateEntry(record.FileName);

           

                    // Opens the created file entry and copies the binary file information of the original file to the file entry in the zip folder.

                    using (System.IO.Stream fileEntryStream = fileEntry.Open())

                    {

                        System.IO.Stream filestream =  BlobUtil::downloadFromBlob(record.DocumentType, record.FileName);

                        filestream.Seek(0, System.IO.SeekOrigin::Begin);

                        fileStream.CopyTo(fileEntryStream);

                        fileStream.Close();

 

                    }

                    record = helper.getNext();

                }

            }        

            File::SendFileToUser(zipStream, zipFileName );

        }     

        DocIntegrationHistoryTable_ds.refresh();

    }


Tuesday, 3 January 2023

Integration between D365FO (AX) and D365CE using API x++

Hello Folks,

I am going to explain customer Asynchronous integration between D365 Finance and operation(F&O) and D365 Customer engagement (CE).

When new D365 F&O customer created or updated or deleted, same information will be available in CE. Every time new token required to access CE.

Prerequisites

  • CE app need to be registered in Azure active directory

Use below snippet of the code and trigger below methods in D365 F&O customer insert/update/delete methods.

using Microsoft.IdentityModel.Clients.ActiveDirectory;

 

class ENCCECustomerIntegration

{

    CustTable   custTable;

    str         url                 = "https://dev.crm.dynamics.com/api/data/v9.2"//CE URL 

    str         aadTenant           = "https://login.microsoftonline.com/b81812e7-dfea-42ed-872e-ed8cf3b20e9f/oauth2/v2.0/token";

    str         aadResource         = "https://dev.crm.dynamics.com";

    str         aadClientAppId      = "";

    str         aadClientAppSecret  = "";

    str         contentType         = 'application/json';

 

    public CustTable parmCustTable(CustTable _custTable = custTable)

    {

        custTable = _custTable;

        return custTable;

    }

 

    public str getAccessToken()

    {

        AuthenticationContext authenticationContext = new AuthenticationContext(aadTenant);       

        var creadential = new ClientCredential(aadClientAppId, aadClientAppSecret);

        AuthenticationResult authenticationResult = authenticationContext.AcquireTokenAsync(aadResource, creadential).Result;

        return authenticationResult.AccessToken;

    }

 

    public RetailWebResponse createCustomer()

    {

        System.IO.StringWriter          stringWriter;

        Newtonsoft.Json.JsonTextWriter  jsonWriter;

        RetailCommonWebAPI              webApi;

        RetailWebResponse               response;

        str                             data;

        str                             postURL;

        str                             header;

        str                             rawResponse;

 

        postURL     = url + "/accounts?$select=cssp_firstname,cssp_lastname,accountnumber,emailaddress1";

 

        //Get access token

        header      = strFmt('Authorization: Bearer %1', this.getAccessToken());

 

        //Format json data

        stringWriter       = new System.IO.StringWriter();

        jsonWriter         = new Newtonsoft.Json.JsonTextWriter(stringWriter);

        DirPersonName   dirPersonName   = DirPersonName::find(custTable.Party);

 

        jsonWriter.WriteStartObject();

        jsonWriter.WritePropertyName("cssp_firstname");

        jsonWriter.WriteValue(dirPersonName.FirstName);

        jsonWriter.WritePropertyName("cssp_lastname");

        jsonWriter.WriteValue(dirPersonName.LastName);

        jsonWriter.WritePropertyName("accountnumber");

        jsonWriter.WriteValue(custTable.AccountNum);

        jsonWriter.WritePropertyName("emailaddress1");

        jsonWriter.WriteValue(custTable.email());

        jsonWriter.WriteEndObject();

 

        data = stringWriter.ToString();

 

        //Call API

        webApi      = RetailCommonWebAPI::construct();

        response    = webApi.makePostRequest(postURL, data, header, contentType);

        rawResponse = response.parmData();

 

        Info("Customer created in the portal.");

 

        return response;

    }

 

    public RetailWebResponse updateCustomer()

    {

        System.IO.StringWriter          stringWriter;

        Newtonsoft.Json.JsonTextWriter  jsonWriter;

        RetailCommonWebAPI              webApi;

        RetailWebResponse               response;

        str                             data;

        str                             patchURL;

        str                             header;

        str                             rawResponse;

 

        patchURL = url + "/accounts(accountnumber='";

        patchURL = patchURL + custTable.AccountNum + "')?$select=cssp_firstname,cssp_lastname,emailaddress1";

 

        //Get access token

        header      = strFmt('Authorization: Bearer %1', this.getAccessToken());

 

        //Format json data

        stringWriter       = new System.IO.StringWriter();

        jsonWriter         = new Newtonsoft.Json.JsonTextWriter(stringWriter);

        DirPersonName   dirPersonName   = DirPersonName::find(custTable.Party);

 

        jsonWriter.WriteStartObject();

        jsonWriter.WritePropertyName("cssp_firstname");

        jsonWriter.WriteValue(dirPersonName.FirstName);

        jsonWriter.WritePropertyName("cssp_lastname");

        jsonWriter.WriteValue(dirPersonName.LastName);

        jsonWriter.WritePropertyName("emailaddress1");

        jsonWriter.WriteValue(custTable.email());

        jsonWriter.WriteEndObject();

 

        data = stringWriter.ToString();

 

        //Call API

        RetailWebRequest request = RetailWebRequest::newUrl(patchURL);

        System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();

 

        request.parmMethod("PATCH");

        request.parmHeader(header);

        request.parmContentType(contentType);

        if (strLen(data) > 0)

        {

            request.setContentBytes(encoding.GetBytes(data));

        }

 

        webApi      = RetailCommonWebAPI::construct();

        response = webApi.getResponse(request);

 

        Info("Customer updated in the portal.");

 

        return response;

    }

 

    public RetailWebResponse deleteCustomer()

    {

        System.IO.StringWriter          stringWriter;

        Newtonsoft.Json.JsonTextWriter  jsonWriter;

        RetailCommonWebAPI              webApi;

        RetailWebResponse               response;

        str                             data;

        str                             deleteURL;

        str                             header;

        str                             rawResponse;

 

        deleteURL = url + "/accounts(accountnumber='";

        deleteURL = deleteURL + custTable.AccountNum + "')?$select=cssp_firstname,cssp_lastname,emailaddress1,statecode";

 

        //Get access token

        header  = strFmt('Authorization: Bearer %1', this.getAccessToken());

 

        //Format json data

        stringWriter       = new System.IO.StringWriter();

        jsonWriter         = new Newtonsoft.Json.JsonTextWriter(stringWriter);

        DirPersonName   dirPersonName   = DirPersonName::find(custTable.Party);

 

        jsonWriter.WriteStartObject();

        jsonWriter.WritePropertyName("cssp_firstname");

        jsonWriter.WriteValue(dirPersonName.FirstName);

        jsonWriter.WritePropertyName("cssp_lastname");

        jsonWriter.WriteValue(dirPersonName.LastName);

        jsonWriter.WritePropertyName("emailaddress1");

        jsonWriter.WriteValue(custTable.email());

        jsonWriter.WritePropertyName("statecode");

        jsonWriter.WriteValue(1);

        jsonWriter.WriteEndObject();

 

        data = stringWriter.ToString();

 

        //Call API

        RetailWebRequest request = RetailWebRequest::newUrl(deleteURL);

        System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();

 

        request.parmMethod("PATCH");

        request.parmHeader(header);

        request.parmContentType(contentType);

        if (strLen(data) > 0)

        {

            request.setContentBytes(encoding.GetBytes(data));

        }

 

        webApi      = RetailCommonWebAPI::construct();

        response = webApi.getResponse(request);

 

        Info("Customer deactivated in the portal.");

 

        return response;

    }

}