Skip to main content

Posts

Showing posts with the label AX

Dynamics eCommerce source control development strategy

Recently, Microsoft released their eCommerce solution. I got started by looking at how to do a bit of development locally. The guide is here https://docs.microsoft.com/en-us/dynamics365/commerce/e-commerce-extensibility/setup-dev-environment One of the first steps to development is to clone Microsoft github repo . That's fairly easy to do. But, the next question I had was, “how do I do my development in my own private version control and continue to pull Microsoft's latest releases?”. I don't want to manually merge folders and deal with painful files. I am not an expert in git and still have a lot to learn. However, below is the approach we have taken and will test out over the coming weeks to see how it works for us. Go to Azure DevOps (my choice of version control) and Import the repository. Click on Import repository. Give it the github URL and name.   After a minute it should show an Import Successful message. Using git bash, clone your Azure DevOps repo by t...

Data Entity stuck “In Process”

There are a few reasons a scheduled data job may not execute. I made a silly mistake and it seemed as though the jobs where stuck on “In process”. Things I checked: 1. Check the job isn’t disabled. See screenshot below. There is a toggle. 2. Check your recurring batch job is scheduled 3. Check you haven’t made any mistakes when enqueuing the entity. (I made a typo here) I made the mistake of copying the URL and not changing the entity name. See the highlighted part in the url. https://myenviornment.cloudax.dynamics.com/api/connector/enqueue/123456789-5506-4314-874D-3CF51A7AE15A?entity= General%20journal &company=usmf Below is a screenshot of the record info. You can see the Entity field contains the string I passed via the enqueue URL. Sounds pretty simple but hopefully helps someone out there.

Recurring import General Journal file using Microsoft Flow #MicrosoftFlow #MSDyn365FO

Microsoft Flow is a simple and cost effective way of integrating. In this post I will walk through how to use Flow for recurring file integration. The most common scenario I can think of is the general journal import. First, I would recommend reading Microsoft article on recurring integration. https://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-itpro/data-entities/recurring-integrations Solution below shows you how to use Microsoft Flow to read from OneDrive for Business and import to FinOps. The exact same thing can be done using Logic Apps for a more enterprise managed solution. Lets start by setting up our folder structure to drop our general journal files in. Create four folders like so: inbound – drop the files here to be processed processing – Flow will move the file here from the inbound folder while executing success – Flow will move it here when the file has successfully been imported and processed error – Flow will move it here if the file fails to process...

Debug Modern POS using .NET Reflector

Respect to all those POS developers. It really requires some dedication and focus to be a POS developer. This is an example of something I would have not figured out without my colleagues. We were working on a development project and we struggled to make sense out of the error. The error we got was complaining about the a method to validate the Unit of measure and Quantity. I was sure the object was not null and I had passed the right thing to it. Unit of measure and quantity fields were populated correctly. The modification was overriding the price. System.NullReferenceException was unhandled by user code    HResult=-2147467261    Message=Object reference not set to an instance of an object.    Source=Microsoft.Dynamics.Commerce.Runtime.Workflow    StackTrace:         at Microsoft.Dynamics.Commerce.Runtime.Workflow.CartWorkflowHelper.ValidateCartLineUnitOfMeasureAndQuantity (RequestContext context, Cart newCa...

Send file to temp blob storage in #MSDyn365FO

In this post I will talk about sending a file to a temporary blob storage. A little warning before I get into it. This is using the Microsoft’s blob storage that is provisioned for us. I haven’t given it a lot of thought on how it would behave in production. Take it at your own risk. Lets start by looking back on a couple of posts last month on printing a report to a byte array. http://dynamicsnavax.blogspot.com/2018/09/print-report-as-byte-array-via-x-in.html http://dynamicsnavax.blogspot.com/2018/09/alternate-way-to-print-report-as-byte.html You can use those sample pieces of code to get a report as a stream and send it to the below code. if (stream) { str fileName = 'myfile'; str contentType = 'application/pdf'; str fileExtension = SRSPrintDestinationSettings::findFileNameType(SRSReportFileFormat::PDF, SRSImageFileFormat::BMP); FileUploadTemporaryStorageStrategy fileUploadStrategy = new FileUploadTemporaryStorageStrategy(); FileUploadTemporarySto...

Find TableId using table browser #MSDyn365FO

I am usually doing this from the development environment. However, I was debugging a customer environment where I only had access to the front end. I had a table that only gave me the RefTableId. I needed to find out the table that record related to. I used SysTableIdView from table browser. Here is the link. http://usnconeboxax1aos.cloud.onebox.dynamics.com/?cmp=usmf&mi=SysTableBrowser&TableName=SysTableIdView

Send to Azure Service Bus in #MSDyn365FO

Sending a message to Azure Service Bus is really simple in FinOps. Below is the job I wrote to send a message to the service bus. It takes a connection string and a queue name for connecting. The message string and key value pair list can be supplied to the properties. static str connectionString = 'Endpoint=sb://navaxservicebus.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=h5KwXSEFIHxxxxxxxxxxxxxxxxxx'; static str queueName = 'navaxqueue'; /// <summary> /// Runs the class with the specified arguments. /// </summary> /// <param name = "_args">The specified arguments.</param> public static void main(Args _args) { if (connectionString && queueName) { Microsoft.ServiceBus.Messaging.QueueClient queueClient = Microsoft.ServiceBus.Messaging.QueueClient::CreateFromConnectionString(connectionString, queueName); Microsoft.Ser...

Alternate way to print a report as a byte array via X++ in #MSDyn365FO

Earlier this month I posted on how to print a report as a byte array . I will do the same but using an alternative method. I will use the print archive instead. You need to create an extension class for the SRSPrintArchiveContract class to add a parm method for the RecId. [ExtensionOf(classStr(SRSPrintArchiveContract))] final class SRSPrintArchiveContract_NAVAX_Extension { public RefRecId navaxPrintJobHeaderRecId; public RefRecId parmNAVAXPrintJobHeaderRecId(RefRecId _navaxPrintJobHeaderRecId = navaxPrintJobHeaderRecId) { navaxPrintJobHeaderRecId = _navaxPrintJobHeaderRecId; return navaxPrintJobHeaderRecId; } public RecId savePrintArchiveDetails(container binData) { RecId recId = next savePrintArchiveDetails(binData); this.parmNAVAXPrintJobHeaderRecId(recId); return recId; } } This is the alternative method I wrote. public static str printSalesInvoiceBase64StrV2(SalesInvoiceId _salesInvoiceId) { ...

Gotcha with Extending Retail Channel transaction table

I will start by pointing you to a good article Andreas Hofmann from Microsoft has written. It steps you through what you need to extend a transactional table in the Retail Channel and bring that back to HQ via the P Job. https://dynamicsnotes.com/extending-a-transactional-retail-channel-table-with-additional-data-hq-x-table-extension-cdx-extension-table-crt-data-service/ Now to summerise the issue I faced recently (being a retail rookie). Following the blog post I created a custom Int64 field on the RetailTransactionSalesTrans. However, when I ran the P job it failed with this error. “Failed to convert parameter value from a String to a Int64” I did some investigation by trying to find out what it is actually doing. Essentially the job will do an outer join to your custom extension table. Even though your custom field is 0 by default. You won’t be creating an extension record for every single transaction record. The p job will do an outer join between RetailTransactionSalesTrans to you...

Print a report as a byte array via X++ in #MSDyn365FO

In the last post I showed how to print the sales invoice as a pdf. In this post we will do the same but generate a byte array of the pdf report. I tried to make the code as readable as possible and hopefully can use it on other reports.. public static str printSalesInvoiceBase64Str(SalesInvoiceId _salesInvoiceId) { str ret; CustInvoiceJour custInvoiceJour; select firstonly custInvoiceJour where custInvoiceJour.InvoiceId == _salesInvoiceId; if (custInvoiceJour) { str ext = SRSPrintDestinationSettings::findFileNameType(SRSReportFileFormat::PDF, SRSImageFileFormat::BMP); PrintMgmtReportFormatName printMgmtReportFormatName = PrintMgmtDocType::construct(PrintMgmtDocumentType::SalesOrderInvoice).getDefaultReportFormat(); SalesInvoiceContract salesInvoi...

Print a Sales Invoice via X++ in #MSDyn365FO

Often you want to print a report via X++. One of the more common reports is the sales invoice. Below is some code you could use to download a pdf copy. I am just picking the first invoice and printing to pdf. Next few posts will be dependent on this. I will try to build up the scenario. public static void printSalesInvoice() { CustInvoiceJour custInvoiceJour; select firstonly custInvoiceJour where custInvoiceJour.SalesId != ''; if (custInvoiceJour) { str ext = SRSPrintDestinationSettings::findFileNameType(SRSReportFileFormat::PDF, SRSImageFileFormat::BMP); PrintMgmtReportFormatName printMgmtReportFormatName = PrintMgmtDocType::construct(PrintMgmtDocumentType::SalesOrderInvoice).getDefaultReportFormat(); SalesInvoiceContract salesInvoiceContract = new SalesInvoiceContract(); salesInvoiceContract.parmRecordId(custI...

Using Global Variables with Retail Modern POS

I am using version 8 platform update 15. Since the POS development is locked out and extensions only is allowed. There are some limitations and a number of objects are not accessible. I was trying to navigate to the customer search and allow the user to select a customer and return to the calling form. This was very challenging. One possible solution I found is to use Global variables. I used the window object. To do this, declare the window object as per screenshot. And then just set your object : eg. window.MyVarName = WhatEverObject; To get the value just invert it. You can see how I have the customer object in debug. Credit to one of my colleagues who suggested this solution.

Automated testing #MSDyn365FO Odata with Postman

In the last post I did a quick run through on using Postman for testing Odata services. This post I will give some tips on how you can write automated tests using Postman. Tip 1 – Parameterise as much as you can Parameterise using the environment settings. It will make your collection portable to other projects. Below is an example where we have the environments settings parameterised. You can see how I used it here. Now I can utilise the same thing across requests. Tip 2 – Write test scripts Test scripts are very easy to work with. This is for demonstration purpose only. I will explain how you can retrieve the values in the returned json. Take the example here, where we use the “get customer” odata service. It returns a nested array with the values. You can write a simple test script to retrieve values. In the below highlighted box you can see that I am logging it to the console. I am not really testing much here. The console will return the below.  One bonus tip here. Just click ...

Testing #MSDyn365FO Odata with Postman

Last year I posted on using Postman. Things have changed since then and I need to update. http://dynamicsnavax.blogspot.com/2017/05/dynamics-365-for-operation-web-service.html There is a good article that Microsoft has written which I followed without any issues. https://docs.microsoft.com/en-us/dynamics365/unified-operations/dev-itpro/data-entities/third-party-service-test#prerequisites Below are some screenshot incase you are a visual person like me. In the environment set ups. It should looks something like this. When you run it, you should get a response. Once you got the token. You are good to go with your messages. Below is the same example from the blog post. You run into any problems, click on the console icon at the bottom. Should give you a bit more information. If you get a 401 error. It is usually a typo. Make sure you got the spaces and backslashes correct. One simple character can drive you crazy.

Top 5 tips for developing a Chatbot

This is different from my usual blog posts but I have been sitting on this for some time. I have been working with Chatbots for about 1 year now. Been on and off various engagements. So, I wrote something to make it a a bit clearer for those wanting to develop it and those wanting to know about it. Chatbots are very trendy these days and thought I would write up some personal learnings I have made. Chatbots have existed for many years but the technology has been democratised like many things in Azure. You can literally build a bot for free of charge (of course you have to invest a bit of your time). A user would generally communicate through a chat window and with the addition of cognitive services, you get a really powerful tool. Below are my top tips for when building your first chat bot. 1. A chat bot must have a purpose There are a few forms of chat bots out there. a) General Chatbots – Alexa, Google, Cortana, Siri, Watson. This is the big problem these major companies mentioned ar...

Resolve Budget dimension through X++ [D365FO]

This one is to resolve budget dimensions. Be careful here to use the right class. Budget plan and Budget register use a different contract class. public static void getBudgetLedgerDimension() { //use BudgetPlanningContract for Budget plan //use BudgetAccountContract for Budget register BudgetAccountContract budgetAccountContract = new BudgetAccountContract(); budgetAccountContract.parmValues(new List(Types::Class)); budgetAccountContract.parmAccountStructure('Manufacturing P&L'); DimensionAttributeValueContract attributeValueContract; //Main account attributeValueContract = DimensionAttributeValueContract::construct('MainAccount', '110180'); budgetAccountContract.parmValues().addEnd(attributeValueContract); //Dimension 1 - repeat this for all other dimensions attributeValueContract = DimensionAttributeValueContract::construct('Departmen...

Resolve default dimension through X++ [D365FO]

This one is resolving the Default dimension public static void getDefaultDimension() { DimensionNameValueListContract dimensionNameValueListContract = new DimensionNameValueListContract(); dimensionNameValueListContract.parmValues(new List(Types::Class)); DimensionAttributeValueContract dimensionAttributeValueContract; //Dimension 1 - repeat this for all other dimensions dimensionAttributeValueContract = DimensionAttributeValueContract::construct('Department', '022'); dimensionNameValueListContract.parmValues().addEnd(dimensionAttributeValueContract); //resolve the dimension DimensionNameValueListServiceProvider dimensionNameValueListServiceProvider = DimensionNameValueListServiceProvider::newForDimensionNameValueListContract(dimensionNameValueListContract); DimensionStorageResult dimensionStorageResult = dimensionNameValueListServiceProvider.resolve(); if (dime...

Resolve ledger dimension through X++ [D365FO]

A bit of code to show how to resolve ledger dimensions. There are various codes out there but I thought I would write it in an easy way to understand. It is hard code but I did that for illustration purposes. public static void getLedgerDimension() { DimensionAttribute dimensionAttribute; DimensionAttributeValue dimensionAttributeValue; DimensionSetSegmentName dimensionSet; DimensionStorage dimStorage; LedgerAccountContract ledgerAccountContract = new LedgerAccountContract(); ledgerAccountContract.parmValues(new List(Types::Class)); ledgerAccountContract.parmAccountStructure('Manufacturing B/S'); DimensionAttributeValueContract dimensionAttributeValueContract; //Main account ledgerAccountContract.parmMainAccount('110180'); //Dimension 1 - repeat this for all other dimensions dimensionAttributeValueContract = DimensionAttributeValueContra...

Integration - Create a lead in CRM via a web service in 10 minutes

CRM (Microsoft Dynamics Online – not AX CRM) has an SDK which you could use to integrate to. It can been overwhelming sometimes. So, I decided to use Flow to do the communication for me (HTTP Request > Dynamics). Took me 10 minutes from start to finish. I didn’t have to learn the CRM SDK or figure out how to do authentication etc. I wanted to send a simple json message like this. {      "Email": "munib@fakeemail.com",      "FirstName": "Munib",      "LastName": "Ahmed",      "Topic": "Health" } Go to Flow and create a new HTTP request. Click on “Use sample payload to generate schema” and enter the above json message. It will generate a schema as per below screenshot. Take note of the HTTP POST URL that has been generated. We will use that later to send the message to. In the Actions select Dynamics > “Create a new record”. Select Leads as the entity name. Map the fields and you are done. Now we just ...