Overcoming FetchXML Limitations: Calculating “Newer-Than-X-Days” with Microsoft Formula Columns

Introduction:

In the realm of Dynamics 365 and FetchXML queries, users often find themselves grappling with limitations, especially when it comes to date filtering. A date filter allowing the display of records “newer” than 90 days from today is currently unavailable. The absence of a straightforward “newer-than-x-days” option in FetchXML has led many to seek alternative solutions. Fortunately, developers like Jonas Rapp and Mark Carrington have proposed workarounds that involve leveraging outer-join functionalities. However, these methods may not simple to implement by end-users. 

The Calculated Field Conundrum: 

Attempting to create a calculated field to bridge the gap presents its own set of challenges. The error message, “This operation cannot be performed on values which are of different Date Time Behaviors,” is a roadblock, particularly when dealing with “Date Only” fields like “Estimated Close Date.” This limitation can be frustrating, hindering the seamless execution of desired date calculations.

A Glimmer of Hope: Microsoft Formula Columns: 

Enter Microsoft formula columns, this alternative method provides a way to perform date calculations without running into the Date Time Behavior mismatch issue. By employing a straightforward formula, users can effortlessly calculate the number of days in the future from the current date.

The Solution: DateDiff Function:

The key to overcoming the FetchXML limitations lies in the DateDiff function provided by Microsoft formula columns. By utilizing this function, users can perform date calculations efficiently. Let’s take a look at a simple example:

DateDiff(UTCToday(), 'Estimated Close Date')

This formula calculates the difference in days between the current date (UTCToday()) and the value in the “Estimated Close Date” field. By using this approach, you can easily filter records based on a “newer-than-x-days” criterion.

Conclusion: 

While FetchXML may present certain limitations, the innovative use of Microsoft formula columns provides a robust solution to the challenge of date filtering. By embracing these alternative methods, users can enhance their Dynamics 365 experience and gain more flexibility in managing and querying data. So, the next time you find yourself grappling with date-related queries, remember the power of Microsoft formula columns to streamline your processes and make your Dynamics 365 journey smoother.

Revolutionizing Business Efficiency: Migrating from a “Broken” On-Premise CRM to Dynamics 365 in the Cloud

Introduction

In the fast-paced world of modern business, digital transformation is the key to staying competitive and relevant. An essential component of this transformation involves transitioning from outdated on-premise systems, such as traditional Customer Relationship Management (CRM) software, to advanced cloud-based solutions. This article explores the journey of migrating from a “broken” CRM system hosted on-premise to Microsoft Dynamics 365 in the cloud. Additionally, it emphasizes the critical role of strategy mapping to ensure alignment between the end system and business processes.

The Legacy of On-Premise Systems

Once considered groundbreaking, legacy on-premise CRM systems often turn into operational hindrances for various reasons:

  1. Maintenance and Upgrades: Maintaining and upgrading legacy systems comes with high costs and disruptions.
  2. Scalability Constraints: Expanding or downsizing an on-premise system is complex and time-intensive, hindering agility.
  3. Accessibility Limitations: On-premise systems restrict accessibility, inhibiting remote work and real-time collaboration.
  4. Integration Complexities: Integrating outdated systems with newer applications can be intricate and costly.
  5. Security Vulnerabilities: Aging systems are susceptible to security breaches and data vulnerabilities.

Elevating Business with Dynamics 365 in the Cloud

Migration to Microsoft Dynamics 365 in the cloud presents a multitude of advantages to address these challenges:

  1. Operational Costs: Cloud-based solutions eliminate upfront hardware investments and ongoing maintenance costs.
  2. Scalability and Flexibility: Dynamics 365 on the cloud adapts resources to demand, ensuring optimal performance.
  3. Remote Accessibility: Cloud platforms enable anytime, anywhere access, fostering remote work and bolstering productivity.
  4. Streamlined Integration: Dynamics 365 offers seamless integration capabilities, connecting with other applications effortlessly.
  5. Robust Security: Microsoft’s cloud services provide robust security features, including encryption and regular updates.

Strategy Mapping: Fusing Technology with Business Ambitions

A triumphant migration to Dynamics 365 hinges on more than just technological decisions. Strategy mapping is pivotal to ensure that the new CRM system aligns with business processes and objectives.

  1. Process Assessment: Before migration, analyze existing processes to identify pain points and opportunities for enhancement.
  2. Clear Goals: Define the CRM migration’s objectives—be it enhancing customer engagement, optimizing sales procedures, or refining data analytics.
  3. Stakeholder Involvement: Engage key stakeholders from various departments to shape the new system according to their needs.
  4. Customized Adaptations: Tailor Dynamics 365 to match your organization’s workflows, accommodating specific processes.
  5. Change Management: Prepare employees for the transition through training and communication about the system’s benefits. Address concerns for smooth adoption.
  6. Continuous Refinement: Regularly evaluate the system’s performance against objectives post-migration. Make necessary adjustments to maintain alignment with business goals.

Conclusion

Transitioning from a “broken” on-premise CRM system to Microsoft Dynamics 365 in the cloud is a strategic move that can rejuvenate business operations. The benefits of cost-effectiveness, scalability, accessibility, integration, and security are compelling reasons to embrace this transformation. Yet, the key to success lies in meticulous strategy mapping that ensures Dynamics 365 aligns seamlessly with business processes and ambitions. By intertwining technological innovation with a comprehensive business strategy, organizations can realize a seamless and impactful digital transformation.

D365 JavaScript: Navigating Autocomplete Control and Address Copying Challenges

Introduction:

Microsoft Dynamics 365 (D365) is a powerful platform that allows businesses to manage various aspects of their operations. Leveraging JavaScript in D365 enables developers to enhance user experience and tailor the application to specific needs. In this blog, we’ll delve into a real-world scenario involving D365 JavaScript, where we encounter an intriguing challenge involving an autocomplete control and address copying.

The Challenge:

Imagine you’re customizing a D365 form, and you have a requirement to provide a user-friendly way for users to select a country using an autocomplete control. Additionally, you’re tasked with creating a checkbox that, when selected, copies all fields from Address 1 to Address 2. While implementing this, you encounter an issue: the JavaScript code you’ve used works seamlessly for all fields except the autocomplete control. Let’s explore this challenge further and discuss the solution you devised.

The JavaScript Code:

The JavaScript code you’ve provided attempts to handle the country field’s autocomplete control and the copying of fields from Address 1 to Address 2. While the code successfully copies field values for text fields, the autocomplete control poses a unique problem. This code works fine for copying the text address fields. For the autocomplete control, we have to save and refresh the page to see the updates.

formContext.getAttribute('address2_country').setValue(newFieldValue);

To get around this problem, I added the following code:

try {
  const element = parent.document.querySelector('[data-id="address2_country.fieldControl_container"] .wj-form-control[aria-label="Country"]');

  if (element) {
      element.outerHTML ='<input class="wj-form-control" style="font-weight: 600; color: rgb(0, 0, 0);" aria-label="Country" readonly type="text" value="' + newFieldValue + '">';
  }
} catch (e) {
  console.log(e.message);
}

In this snippet, you use the `setValue` method to set the value of the ‘address2_country’ attribute to `newFieldValue`. Subsequently, you attempt to manipulate the autocomplete control by locating the corresponding element and replacing it with an input element containing the new value.

The Autocomplete Control Challenge:

The issue you’re encountering with the autocomplete control stems from its complex nature. Autocomplete controls in D365 often involve intricate components and interactions that standard text input fields do not exhibit. My approach was to directly manipulating the element’s HTML element.

Conclusion:

Working with D365’s JavaScript capabilities can be immensely rewarding, but it can also present unique challenges, as demonstrated by the scenario of the autocomplete control and address copying. While your initial approach exhibited promise, autocomplete controls often require more intricate handling. By refining your strategy and exploring D365’s native methods and community resources, you can conquer this challenge and unlock the full potential of JavaScript customization in D365. Remember, JavaScript in D365 is a powerful tool – with a bit of creativity and perseverance, you can overcome any obstacle it presents.

Writing Dynamics C# Console App With Only Two Dependent Packages

Writing C# code for Dynamics 365 opens up numerous possibilities within the platform. It enables the ability to update data in Dynamics (Dataverse) and facilitates integration scenarios, such as connecting external systems with Dynamics. However, one of the common challenges we encounter is the dependency on the .NET version utilized by Dynamics, which currently mandates .NET 4.6.2 and entails several dependencies. These dependencies can present problems, particularly in larger projects. Surprisingly, even for a simple C# application, the list of dependencies can become quite extensive. To make matters worse, one of the dependencies, Microsoft.IdentityModel.Clients.ActiveDirectory, has been deprecated.

How do we get around so many dependent packages? What if we want to run our code under a newer .NET version like 6.0 or .net core 3.1? The good news is that we now have a great solution called Dataverse Client. The code is available on: GitHub PowerPlatform DataverseServiceClient

What’s really nice is that there are only two dependencies to run a simple console application:

DataverseCRUD.cs

Here is a sample CRUD program that connects to Dynamics 365, then create an account, read the account, update it and then delete it.

using System;
using Microsoft.PowerPlatform.Dataverse.Client;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Extensions.Configuration;

namespace DataverseClientCRUD
{
    class Program
    {
        static void Main(string[] args)
        {
            var builder = new ConfigurationBuilder()
                     .AddJsonFile("appsettings.json", true, true);
            IConfiguration config = builder.Build();
            string connectionString = config["ConnectionStrings:MyCRMServer"];
            using var serviceClient = new ServiceClient(connectionString);

            CRUD(serviceClient);
        }

        private static void CRUD(ServiceClient serviceClient)
        {
            //Create
            Console.WriteLine("**** Create ****");
            Entity account = new Entity("account");
            account["name"] = "ABC Corporation";
            account.Id = serviceClient.Create(account);

            //Read
            Console.WriteLine("**** Read ****");
            Entity readAccount = serviceClient.Retrieve(
                entityName: account.LogicalName,
                id: account.Id,
                columnSet: new ColumnSet("name")
            );
            Console.WriteLine("Retrieved account name: {0}", readAccount["name"]);

            //Update
            Console.WriteLine("**** Update ****");
            account["name"] = "ABC Corp";
            serviceClient.Update(account);

            //Delete
            Console.WriteLine("**** Delete ****");
            serviceClient.Delete(account.LogicalName, account.Id);
            serviceClient.Dispose();
        }
    }
}

appsettings.json

Create an appsettings.json file in Visual Studio and set the file to copy to output directory:

 

{
  "ConnectionStrings": {
    "MyCRMServer": "AuthType=ClientSecret;Url=https://XXXX.crm.dynamics.com;ClientId=XXXX;ClientSecret=XXXX"
  }
}

Dynamics 365 Interactive Dashboard Showing Inaccurate Data

Interactive Dashboards in Dynamics 365 are highly valuable and offer crucial business insights into the data. However, I encountered an issue recently where the chart counts did not align with the stream counts. While the dashboard displayed the accurate data on the development server, the production server failed to reflect the correct chart counts in comparison to the stream (Grid on the left side). It’s important to note that the stream did display the correct counts, but the individual chart components did not.

Creating a new interactive dashboard fixed the problem, however I had end-users creating customized filters and I didn’t want to have to train them on how to recreate the filters. 

I decided to create a new solution with just the dashboard component and compare the solutions between the development copy and production copy. My handy Notepad++ compare utility showed me what’s different. Somehow during the deployment to production, the default view was pointing to a different GUID. I repackaged the solution and deployed to production and it started working again. Hopefully this will help others.

Dynamics 365 WebAPI Asynchronous Calls

Column Editing Text Editor Editing Dynamics 365 development is a constantly evolving field, with the JavaScript API being no exception. Exciting advancements have been made in this space, such as the introduction of WebApi’s method, which allows for basic CRUD operations (Link).

Gone are the days of worrying about including JSON files or calling jQuery libraries just to make simple API calls. The platform now provides straightforward methods for performing basic CRUD operations.

To illustrate this, here’s a simple example. I utilized the fantastic REST Builder tool to generate the code. This code searches for an email address and retrieves the full name of the corresponding contact record.

function FindContactRecord(email) {
    Xrm.WebApi.online.retrieveMultipleRecords("contact", "?$select=fullname&$filter=(emailaddress1 eq '" + email + "')&$top=1").then(
        function success(results) {
            var result = results.entities[0];
            var fullname = result["fullname"];
            ProcessData(fullname);
        },
        function (error) {
            console.log(error.message);
        }
    );
}

The above code works great for a single record, since the ProcessData function gets invoked in the success function of the WebAPI call. When we start to do bulk operations, the code starts executing asynchronously. Here is an example of calling the function multiple times. This code is only for illustrations purposes. If we were to query multiple contact records, our best practice is to batch multiple email addresses into a single WebAPI call.

function FindContactRecords(EmailArray) {
    var contactFullnames = new Array();
    for (var i = 0; i < EmailArray.length; i++) {
        contactFullnames.push(FindContactRecord(email[i].trim()));
    }
    return contactFullnames;
}

function FindContactRecord(email) {
    Xrm.WebApi.online.retrieveMultipleRecords("contact", "?$select=fullname&$filter=(emailaddress1 eq '" + email + "')&$top=1").then(
        function success(results) {
            var result = results.entities[0];
            var fullname = result["fullname"];
            return (fullname);
        },
        function (error) {
            console.log(error.message);
        }
    );
}

//Main function 
var contactFullnames = FindContactRecords(EmailArray);
ProcessData(contactFullnames);

The main issue we face with the above code is that the contactFullname array will not return elements since JavaScript engine is executing the WebAPI calls asynchronously for performance reasons.

So how do we fix this problem? By using async, await and then statements, JavaScript will return a promise which will not execute subsequent code until the async code completes processing. The changes in blue illustrates the required changes.

async function FindContactRecords(EmailArray){
    var contactFullnames = new Array();
    for (var i = 0; i < EmailArray.length; i++) {
       await contactFullnames.push(FindContactRecord(email[i].trim()));
    }
    return contactFullnames;
}

async function FindContactRecord(email) {
    await Xrm.WebApi.online.retrieveMultipleRecords("contact", "?$select=fullname&$filter=(emailaddress1 eq '" + email + "')&$top=1").then(
        function success(results) {
            var result = results.entities[0];
            var fullname = result["fullname"];
            return (fullname);
        },
        function (error) {
            console.log(error.message);
        }
    );
}

//Main function 
FindContactRecords(EmailArray).then(
    contactFullnames => ProcessData(contactFullnames)
);

There are many articles that discusses async/await, but how to applies to Dynamics 365 is not something well covered. I hope this  article helps.

Ongo Homes of your back office systems provides 10,000 homes for people

Overview

Sure, the technology has come a long way since then, and the variety of the information objects we’re managing has changed a lot, but one tenet has remained constant we’ve always focused on the intersection of people, processes, and information. As the Association for Intelligent Information Management, we help organizations put their information to work.

Tenet has remained constant: we’ve always focused on the intersection of people, processes, and information. As the Association for Intelligent Information Management, we help organizations put their information to work.

Problems

Sure, the technology has come a long way since then, and the variety of the information objects we’re managing has changed a lot, but one tenet has remained constant we’ve always focused on the intersection of people, processes, and information. As the Association for Intelligent Information Management, we help organizations put their information to work.

Challenge

Technology has come a long way since then, and the variety of the information objects we’re managing has changed a lot, but one tenet has remained constant we’ve always focused on the intersection of people, processes, and information. As the Association for Intelligent Information Management, we help organizations put their information to work.

Solution

Technology has come a long way since then, and the variety of the information objects we’re managing has changed a lot, but one tenet has remained constant we’ve always focused on the intersection of people, processes, and information. As the Association for Intelligent Information Management, we help organizations put their information to work.

Ongo Homes of your back office systems provides 10,000 homes for people

Overview

Sure, the technology has come a long way since then, and the variety of the information objects we’re managing has changed a lot, but one tenet has remained constant we’ve always focused on the intersection of people, processes, and information. As the Association for Intelligent Information Management, we help organizations put their information to work.

Tenet has remained constant: we’ve always focused on the intersection of people, processes, and information. As the Association for Intelligent Information Management, we help organizations put their information to work.

Problems

Sure, the technology has come a long way since then, and the variety of the information objects we’re managing has changed a lot, but one tenet has remained constant we’ve always focused on the intersection of people, processes, and information. As the Association for Intelligent Information Management, we help organizations put their information to work.

Challenge

Technology has come a long way since then, and the variety of the information objects we’re managing has changed a lot, but one tenet has remained constant we’ve always focused on the intersection of people, processes, and information. As the Association for Intelligent Information Management, we help organizations put their information to work.

Solution

Technology has come a long way since then, and the variety of the information objects we’re managing has changed a lot, but one tenet has remained constant we’ve always focused on the intersection of people, processes, and information. As the Association for Intelligent Information Management, we help organizations put their information to work.

Virtual environment in order to scale up their back office of your back office systems

Overview

Sure, the technology has come a long way since then, and the variety of the information objects we’re managing has changed a lot, but one tenet has remained constant we’ve always focused on the intersection of people, processes, and information. As the Association for Intelligent Information Management, we help organizations put their information to work.

Tenet has remained constant: we’ve always focused on the intersection of people, processes, and information. As the Association for Intelligent Information Management, we help organizations put their information to work.

Problems

Sure, the technology has come a long way since then, and the variety of the information objects we’re managing has changed a lot, but one tenet has remained constant we’ve always focused on the intersection of people, processes, and information. As the Association for Intelligent Information Management, we help organizations put their information to work.

Challenge

Technology has come a long way since then, and the variety of the information objects we’re managing has changed a lot, but one tenet has remained constant we’ve always focused on the intersection of people, processes, and information. As the Association for Intelligent Information Management, we help organizations put their information to work.

Solution

Technology has come a long way since then, and the variety of the information objects we’re managing has changed a lot, but one tenet has remained constant we’ve always focused on the intersection of people, processes, and information. As the Association for Intelligent Information Management, we help organizations put their information to work.