Dynamics Customer Service form – Simple yet functional

This post is a part of a series of posts for Customer Service. The complete GUIDE can be found here

Before we complete it all I will clean the form a bit. The demo I will be focusing on is the B2B space. If you use the B2C part of support, you might not need any of this. Just continue to the next post:)

Before

It looks good out of the box, but it doesn’t provide a great amount of value.

  1. Business Process Flow on the top of this case is close to useless. It only indicates that you can have a process that looks nice. The steps don’t make sense, and as always with BPF…. You can’t create a step without a mandatory field present. 😒
  2. The first quick view shows a view of the company information. It takes up a lot of space, and in my opinion displays relatively irrelevant information about the customer. If you want quick info about customer, you can “hover over” the customer field.
  3. The right side is setup with reference panels. I wrote an article about loving them a while back, but Customers seem to prefer normal subgrids when actually navigating. Recent Cases is actually just a quick view, and that doesn’t do us much good. Try opening one of the cases, and you won’t see much. We will have to clean this up for it to actually work. We will also remove entitlements, because it’s too much of a hassle in a simple Customer Service scenario.
  4. I hide the tabs on top for now, because I simply don’t need them. If at one point you want to expand, you can reintroduce them.
  5. Subjects.. Are they staying or going. I am not sure what the future holds for this. It’s quite confusing. At some parts of history it seemed very central for Customer Service and Knowledge Articles. Then Categories came along. I would like some clear information what is what. For simplicity I will use subjects for demo. Personally not to happy about it.
  6. The customer field here is as confusing at the customer field was originally for Opportunity. If you are using Customer Service for B2B this has to be linked to an account and not contact. If you use B2C I guess you can just leave it and never really see it as a problem. In my cases I always have to change this to store Account, and then use the Contact field for Contact. Opportunity has managed to change from Customer field to Account & Contact. Don’t see why Case can’t do the same…

Cleanup

1. BPF – Business Process Flow removal

Start off by deactivating the BPF from customization. Then we have to delete all records of the process running. Open Advanced Find, and look for the table that has the same name as the Business Process Flow

PS: If you happen to have a demo setup, it might also include Field Service demo data. Then you have to repeat the process for “Case to Work Order Business Process”.

2. Quick View

Does not give any extra added value. I am replacing this function with a similar value, but different way of working. I open in form editor and remove.

3. Remove Entitlements in Reference Panel

First make sure to remove the Entitlements

Then make sure that the view is set to Recent Cases. Don’t trust that the name of the subgrid is correct. You actually have to make sure that you have the Recent Cases view here.

Create a new section for Recent Cases, and move the Recent Cases out of the Reference Panel. This way we can actually click on a case and open it from the Quick View.

4. Hide tabs

Just hide it. Don’t need it for now

5. Fix Customer field – B2B scenario

In the B2B scenario we need to make a few adjustments to the customer field, and add some onload logic for the agent. In the B2B scenario we need the customer data to be good, and therefore we can’t accept cases where the contact is unknown.

Check this article on how to fix the Customer/Contact fields

6. Subject

Remove unwanted subjects.

Result

Let’s just agree that this doesn’t look very exciting, but it does the job. It does the job quite well!

This is how I want it to look. I have hidden a bunch of components that Microsoft includes as standard Customer Service. Normally it is just a little too much. This will lead to an easy training and a simple customer service view for the agent.

Removing the Business process flow we loose a lot of colors, but this is for actual production. Not a fancy demo to excite someone buying.

Dynamics Customer Service – B2B scenario

This post is a part of a series of posts for Customer Service. The complete GUIDE can be found here

Many years ago Opportunity retired the Customer field and replaced it with Primary Contact and Primary Account fields. Case has not yet done this for reasons I can’t really understand. As you will see in this article we achieve the same result when adding the contact field, but the customer field is still a polymorphic lookup.

Email to Case could easily add to the contact field instead of the customer field. Field service is actually dependent on account being in the customer field for it to work properly.

This is how Case has to be setup to make sense in the B2B world:

If the Contact and Customer are known to the system, they will automatically populate. If the Contact is new to the system, the connection to the Account will be missing. In this case we need to alert the Agent, and ask them to update the contact record.

JavaScript

The following JavaScript is added to the Case form. It checks the Customer field to see if it is contact. If this is the case, it will check if the Contact has a Account connected. Most likely it will not have an Account, so we will be prompted “Do you wish to update the Contact?”. Answer YES here, and a quick view of the Contact will appear. Update Account, and then the JavaScript will do the rest for you. ✨MAGIC✨

var formContext = "";

function OnCrmPageLoad(executionContext) {
    formContext = executionContext.getFormContext();
    
    //
    //You don't need to change this. Just understand that forms have one the following states when opening
    //
    var FormTypes =
    {
        Undefined: 0,
        Create: 1,
        Update: 2,
        ReadOnly: 3,
        Disabled: 4,
        QuickCreate: 5,
        BulkEdit: 6
    }
    runAlways(formContext);
    switch (formContext.ui.getFormType()) {
        case FormTypes.Create: OnNewFormLoad(); break;
        case FormTypes.Update: OnUpdateFormLoad(); break;
        case FormTypes.ReadOnly: OnReadOnlyFormLoad(); break;
        case FormTypes.Disabled: OnDisabledFormLoad(); break;
        case FormTypes.QuickCreate: OnQuickCreateFormLoad(); break;
        case FormTypes.BulkEdit: OnBulkEditFormLoad(); break;
        case FormTypes.Undefined: alert("Error"); break;
    }
}

//
//I only use the RunAlways, OnNewFormLoad and OnUpdateFormLoad, but i keep the others here if i ever would need. 
//When looking at this you can always know what funtion is running. Easy to read and debug. 
//
function runAlways() { }
function OnNewFormLoad() {}
function OnUpdateFormLoad() {
    //
    //Clean up Contact Data. If contact has account, but account not in Customer field perform update. If Contact doen's have account ask for update
    //
    GetAccountInfo();
}
function OnReadOnlyFormLoad() { }
function OnDisabledFormLoad() { }
function OnQuickCreateFormLoad() { }
function OnBulkEditFormLoad() { }


//******************************************************************** */
//CUSTOM FUNCTIONS are added below here. Below this point you add all types of functions you need. 
//******************************************************************** */
function GetAccountInfo() {
    var CustomerField = formContext.getAttribute("customerid").getValue();
    if (CustomerField != null) {
        if (CustomerField[0].entityType == "contact") {
            var CustomerGUID = CustomerField[0].id;
            CustomerGUID = CustomerGUID.replace("{", "");
            CustomerGUID = CustomerGUID.replace("}", "");

            //
            //If the Customer Field contains a contact, I want to change this. I want the Customer Field to be an account. Step 1 is to find out if the contact has account registered.
            //
            Xrm.WebApi.online.retrieveRecord("contact", CustomerGUID, "?$select=_parentcustomerid_value").then(
                function success(result) {
                    var Id = "{" + result["_parentcustomerid_value"] + "}";
                    var Name = result["_parentcustomerid_value@OData.Community.Display.V1.FormattedValue"];
                    var LogicalName = result["_parentcustomerid_value@Microsoft.Dynamics.CRM.lookuplogicalname"];

                    //
                    //IF the contact has an account I move the Contact to Case Contact, and receive the Account from the Contact and enter it to Customer on Case.
                    //
                    if (LogicalName != null){
                        formContext.getAttribute("primarycontactid").setValue(CustomerField);
                        formContext.getAttribute("customerid").setValue([{ id: Id, name: Name, entityType: LogicalName }]);
                        formContext.data.entity.save();
                    }else{
                        //
                        //Promt if you want to open contact for update?
                        //https://carldesouza.com/how-to-implement-javascript-confirmation-dialogs-in-power-apps-and-dynamics-365/ - THANK YOU
                        //
                        var confirmStrings = { text:"Contact is not connected to Account. Please update!", title:"Data Update Recommended", confirmButtonLabel:"Open Contact", cancelButtonLabel: "Not Now" };
                        var confirmOptions = { height: 200, width: 450 };
                        Xrm.Navigation.openConfirmDialog(confirmStrings, confirmOptions).then(
                        function (success) {    
                            if (success.confirmed){
                                //
                                //If the user chooses to update, I open a small contact form, and make the user set the Account. 
                                //After Save&Close i recall this function, and then I update Account and Contact for case. 
                                //
                                Xrm.Navigation.navigateTo({pageType:"entityrecord", entityName:"contact", formType:2, formId:"e4206691-b1e3-4e9d-a23a-4865b9511091", entityId:CustomerGUID}, {target: 2, position: 1, width: {value: 20, unit:"%"},height: {value: 50, unit:"%"}}).then(
                                    function success() {
                                        GetAccountInfo();
                                    },
                                    function error() {
                                        alert("The system was not able to save the change. Please reload the page and try again");
                                    }
                                );
                            }else{
                                //Say or do something if the user doesn't update Contact
                            }
                        });

                    }
                },
                function (error) {
                    Xrm.Utility.alertDialog(error.message);
                }
            );
            
        }
    }

}

Result

If Gus creates a top 10 PCF components, I hope this one makes it ;)

If you ever had a problem with navigating between entities for updating data, this PCF component will absolutely save a lot of time.

Clement Olivier
https://stuffandtacos.azurewebsites.net/
@Clement0livier – Twitter
https://github.com/carfup/PCFControls – download the tool

He created a PCF component for quick updating related entities without having to leave the record.

Updating related LOOKUP

Internally we have all of our active projects in a list. For every project we have a customer contact registered for continuous surveys (Power Automate, Forms Pro, SMS.. Cool Stuff). For the system to work correctly we need to make sure we have both the phone number and email address updated at any given time for the automated surveys to work.

What would we do without devs!!:)

Managed solutions Update vs Upgrade vs Stage

I haven’t touchet managed solutions for quite some time, so importing a managed solution recently surprised me:)

This article is not explaining the differences in detail, but I wanted to make sure you knew there is a difference between upgrade and update. I don’t understand why Microsoft insist on recommented the way they do. I feel you need to know the project before this is a certainty.

Upgrade

New for me is the option of upgrading. If you remove an item in the source managed file, this will now actually delete it in the destination. Say you remove a field on account this should remove the field in the destination.

Do you remember the old ways of doing it?
Introduced arround 2011 OR Introduced arround 2015

Stage for Upgrade

A great way to test something before committing to any changes. I would not use this for an ISV solution, but if you happen to use Managed internally this might be a way to go.

Update

This is marked as the Not Recomended option, but I still feel this is the normal way to do. If you are doing an ISV import this doesn’t matter because the solution file probably is correct, but if you are working with managed internally, I would use this just because I might not trust someone in dev doing config 100% correctly…

Source
Microsoft DOC

Business Process Flow set Pipeline Phase

I was never a fan of the Business Process Flow (BPF) because of the many flaws. Sometimes I didn’t think it was easy enough, and other times not advanced enough. It simply wasn’t what I needed.

In a recent project I decided to give it another go, because the customer wanted to continue with the BPF they had from their old CRM system.

Opening the PBF now I see that there is so much new features here that I haven’t seen before. I guess most of these features are due to the FLOW platform now taking over the BPF.

Challenge: Setting pipeline phase

I know you can report on the BPF entity, but that is more complex than reporting on the opportunity entity if you ask me.

Can I set the “Phase” field on the opportunity when navigating to the next step in the BPF? Let’s see!!

I wanted to set the Pipeline Phase with BPF

Config

Open the Business Process Flow from your solution and notice a button at the bottom right “Business rules for this stage’s entity”.

Create a new Business Rule for Opportunity “Oppty – Set Pipeline Phase”.

For the first condition we check if the BPF is in the stage named Prospect.

If true, set the Pipeline Phase to “1 – Qualify”.

Repeat for the second step!

The business rule should look something like this:

Result

Let’s get back to the Opportunity. We see that it default is active on the Qualify stage in the beginning of the sales process.

Click the next stage

And there you go!!

New Found Love

So what do I think of the BPF now? Honestly, I liked it. It might be a replacement for many other JavaScripts that I have been using the later years, and that is only a good thing. In this case I was able to skip JavaScript and therefore deliver a solution with a low technical footprint:)

Flow – Create, Update or Delete trigger error

At the time of writing this post Microsoft Flow will throw an error when you create this flow with the trigger Create, Update or Delete, and the flow is standalone.

Error

This is the following error you will see when you try to create the flow (Create, Update, Delete) without any connection to a solution.

Sollution

All you have to do, is open this in a solution (for the time being).