Archive for category N:N Relationships

Crowdsourcing the ultimate Sales Dashboard for Dynamics 365/CRM

When setting up a new Dynamics 365/CRM trial a few standard dashboards are included. However, I feel they lack something, and those who follow me on Twitter know I occasionally like to make fun of particularly the funnel chart. So here’s a hopefully improved version, that you can use, either in your organization or simply to spice up a demo environment.

Well, why not do something about it then. Plus, I’ve toying with this idea for a while anyway.

Crowdsourcing?

I did have the audacity to use the term “ultimate” in the title and the dashboard I provided is clearly not. However, with lots of input, we can make this much better.

Therefore; I would love to hear from you if you have suggestions how to make these dashboards better.

Suggestions could include, but are certainly not limited to:

  • Ideas for new KPIs
  • Ideas for new Charts
  • Ideas to improve formatting and make the charts easier to decode
  • Using charts contextually on record forms
  • Better use of colors between the different charts

My only request is that you elaborate on your suggestion, and I will try to incorporate as much as possible and hopefully have this grow into something very useful.

At the bottom of this post, I’ve included a zip file containing a solution with all the components for the dashboards in this post. The zip file contains both a managed and unmanaged solution that can be imported to Dynamics 365/CRM, and all the chart xml files individually.

Assumptions

It should be possible to import the charts on Dynamics 365/CRM organizations, so I will try to adhere to the following rules and assumptions:

  • Only use the charts within Dynamics 365/CRM*
  • Only use system fields
  • Only use system relationships
  • Avoid using calculated fields for KPIs – unless it is a system field
  • Take as much advantage of the existing setup as possible

*Why am I limiting myself to only using the charts within Dynamics 365/CRM and not including Power BI and Customer Insights. While Power BI and Customer Insights are powerful features, they are both tools external to Dynamics 365/CRM. You cannot as easily, share the charts and KPIs within CRM itself. Charts also have some significant advantages too. They can be contextual to the user logged in, respects the security roles, and they are real-time. “I just won an opportunity. I’ll happily wait an hour and then look at the sales leaderboard to see my position.” said no sales person ever!

 

The Sales Dashboard

Main sales dashboard with the most important KPIs for Dynamics 365/CRM

The Sales Dashboard consists of the following charts:

1. Sales Funnel

Somehow it is not a sales dashboard if there isn’t a funnel on it. It is the universal indicator of a sales process regardless of how wrong it may be. I have done my best to overcome some of those areas.

2. Sales Leaderboard

The Sales Leaderboard is also a standard component on a sales dashboard. This one includes both won and in progress revenue. Users are ranked per the amount won. Current user is emphasized in a stronger color so it is easier to see your own position.

3. Sales KPIs about the open opportunities

KPIs include est. revenue, average value, number of opportunties in the pipeline, next est. close date and date the last opportunity was created. On the dashboard, the user can flip views between “Open Opportunities” vs. “My Open Opportunities” to get both group and personal KPIs.

4. Phase Loss Rate on Est. Revenue

This chart gives you the percentage of revenue lost per phase in the sales pipeline. For example, in the qualify stage, if opportunities est. 100 million entered the qualify stage, but only 45 million of est. revenue made it to the develop phase, then the loss rate for qualify is 65%. The same calculation for the develop phase, but of course excluding all the opportunities that never made it that far. In an ideal world, you would lose more opportunities in the initial stages and have a much higher win percentage towards the end.

Additional charts with variations on how the calculations are made are included in the zip file, including using the number of opportunities rather than the est. revenue.

5. Sales KPIs for Won Opportunities

Like the other KPI chart, but this one focusing on KPIs for the opportunities that were won.

Competitor Strength

Scroll down on the dashboard and you get to the Competitor Strength chart.

Competitor Strength for Open Opportunities in Dynamics 365/CRM

The competitor strength chart lists all your competitors, ranked by how many opportunities you have lost to them.

On top of the lost bar, you can see how many opportunities are currently in progress.

Finally, in another bar, you have the est. revenue of the open opportunities where this competitor is a threat.

Sales Pipeline Analysis

Sales Pipeline Analysis in six charts in Dynamics 365/CRM

As mentioned earlier, I have included all the pipeline analysis charts in one dashboard for review. They all work in the same manner, although the calculations have a different focus as described by their names.

Download

As always, samples are provided for fun and training purposes only. Test properly prior to using in a production environment.

Sales Dashboard by CRM Chart Guy Version 0.0.0.1

Update Notes November 20, 2016.

Pipeline Charts now only uses the beginning number of the step name, so as long as your phases are 1 through 4, then you would not need to make changes. Won opportunities will also be filtered correctly and do not necessarily need to be moved to the close stage. Regardless of the stage on a won opportunity, it is assumed that it has made it through all the stages.

Added some of the pipeline charts to a separate User form to analyze an individual’s performance against how the company KPIs.

Zip file includes all the chart xml files individually and a managed and unmanaged version of the solution file for Dynamics 365.

Solution files for pre-Dynamics 365 environments are no longer included. However, all the chart xml files can be imported separately into previous versions. Presumably, all the way back to CRM2011 although I have not been able to test that.

Added a chart for the Opportunity Products to see what products are in the pipeline. Products less than 10% of the total are grouped into “Other”.

Original Solutions Notes

All the charts that use stages or the pipeline rely on the Opportunity field called Pipeline Phase. Most trial instances have data in this already. Otherwise, it is populated either manually or by a workflow. The chart also assumes that the naming of the phases is kept from the trial so they are called 1-Qualify, 2-Develop etc.

The assumption I made in the calculations is that won opportunities are in the 4-Close phase. Therefore, make sure that the process that updates the pipeline phase puts won opportunities 4-Close. They really should be in that stage anyway if won.

The solution files with Dyn365 in the name are specifically for new trials or environments that have already been upgraded. This solution also includes the Competitor Chart.

Solution files with CRM_8.0 in the name are for CRM2016 and earlier. This version does not include the competitor strength chart as there’s a bug in CRM that does not allow the distinct=true property to be imported in a solution file. This was fixed with Dynamics 365.

All the chart xml files are in the zip file as well, so you can import them separately, make modifications etc.

Thanks for reading. Hope you enjoy and please share and let me know of any good suggestions.

And don’t forget to sign up for my newsletter on this page and follow me on Twitter

, , , , , , , ,

12 Comments

N:N Relationship Charts in MS Dynamics CRM

N:N Relationships, or Many-to-Many Relationships, can be a little tricky to get information out of.

As an example competitors out-of-the-box have an N:N relationship with opportunities. Let’s say we wanted to look at a list of competitors and see how many active opportunities they are currently engaged in. With the chart editor and views, the best bet is to open each competitor record and count how many active opportunities it is related to. We can make that much easier with a chart like this.

Count and sum of estimated revenue for opportunities, per competitor chart in MS Dynamics CRM.

Count and sum of estimated revenue for opportunities, per competitor.

Before I get started on how to build the chart, let’s first have a look at how N:N relationships are structured in MS Dynamics CRM.

I will use the competitor opportunity relationship as an example, but this applies to all system and custom N:N relationships.

While it is not apparent in the solution designer, the relationship is controlled by an intersect table, in this case called “opportunitycompetitors”.

Table structure for competitor to opportunity N:N relationship in MS Dynamics CRM.

The intersect table is a system entity.

We will need this exact name of the intersect table for the fetchcollection in our chart xml.

To find the name of the intersect table, open up competitors for customization in the solution editor.

3 Solution Editor See NN relationships

Click N:N Relationships and open the relationship to opportunity.

4 Relationship Entity Name

Here, find the “Relationship Entity Name” towards the bottom of the form and make a note of the exact name for later.

Now that we have the name of the intersect table, on to building the chart. A full sample of the chart xml can be downloaded at the bottom of this post.

Build The Base Chart

As always, I start by creating a base chart I can use for editing the chart xml. I am starting on the competitor entity.

2 Create Base Chart

A simple bar chart counting competitors, grouped by competitor. Not very useful yet.

Simple – Count Opportunities Per Competitor

Export the xml and open it in your xml editor (Notepad++ perhaps).

Here’s the fecthcollection. I have renamed the obscure aliases to something more sensible. This is where we will do most of the work. If you change the aliases too, remember to also change them in the categorycollection.

      <fetchcollection>
        <fetch mapping="logical" aggregate="true">
          <entity name="competitor">
            <attribute groupby="true" alias="GroupBy" name="name" />
            <attribute alias="CountOfOpportunities" name="name" aggregate="count" />
          </entity>
        </fetch>
      </fetchcollection>

Now I want to change the chart xml, so I get a link to the intersect table and can count the number of relationships the competitor has to opportunities.

      <fetchcollection>
        <fetch mapping="logical" aggregate="true">
          <entity name="competitor">
			<link-entity name="opportunitycompetitors" from="competitorid" to="competitorid">
				<attribute alias="CountOfOpportunities" name="competitorid" aggregate="count" />
			</link-entity>
            <attribute groupby="true" alias="GroupBy" name="competitorid" />
          </entity>
        </fetch>
      </fetchcollection>

I have now created a link to the intersect table and placed the count aggregate inside of it. The groupby is still directly on the competitor entity. I also changed the name of the count attribute to “competitorid”. This is because the intersect table only holds the id fields.

Import to MS Dynamics CRM and look at the result.

Count of opportunities per competitor via the intersect table in MS Dynamics CRM.

Count of opportunities per competitor.

Now we have a list of competitors including a count of how many opportunities they are competing on.

On import you may run into this error message.

Error

If that happens, just change the width of the chart or refresh the page and it will work.

Advanced – Count and Sum of Estimated Revenue from Opportunities

That was charting on N:N relationships in its simplest form. However, as always we would like to do more. How about including the sum of the estimated revenue of those opportunities, and also filter it to only include active opportunities.

In order to achieve that, we need to add an extra link-entity to get all the way to the opportunity entity, so we can access fields there directly. In the first example we stopped on the intersect table.

Sample of fetchcollection which links from competitor, via the intersect table, to the opportunity entity.

      <fetchcollection>
        <fetch mapping="logical" aggregate="true">
          <entity name="competitor">
            <link-entity name="opportunitycompetitors" from="competitorid" to="competitorid">
				  <link-entity name="opportunity" from="opportunityid" to="opportunityid">
						<filter type="and">
						  <condition attribute="statecode" operator="eq" value="0" />
						</filter>
						<attribute alias="CountOfOpportunities" name="opportunityid" aggregate="count" />
						<attribute alias="EstimatedRevenue" name="estimatedvalue" aggregate="sum" />
				  </link-entity>
            </link-entity>
            <attribute groupby="true" alias="GroupBy" name="competitorid" />
          </entity>
        </fetch>
      </fetchcollection>

We now have two sets of <link-entity>, linking through the intersect table to the opportunity entity.

Notice the pattern in the links are name=”intersectable” from=”field with id from intersect table” to=”field with id from starting entity” and in the next line it is name=”the other entity” from=”field with id on other entity” to=”field with id on intersect table”. Since the id fields are mostly the same, once you have the name of the intersect table, these are fairly straight forward. Marketing lists are an exception to this.

Inside the <link-entity> to the opportunity entity, I have added a filter so we only include active opportunities. As usual, I just created a view in Advanced Find, downloaded the fetchxml, and copied the part with the filter.

I also added an extra attribute to include the sum of the estimated revenue for the opportunities.

Here’s what the final chart looks like.

N:N relationship chart in MS Dynamics CRM using only standard xml customizations in the chart xml.

Opportunities and sum of estimated revenue per competitor.

I also made these optimizations to the chart, just to touch it up a little.

  • In the Series
    • LabelFormat=”C0″  – so values in the chart have no decimals – that’s the letter “C” followed by a zero
    • DrawingStyle=Cylinder – in the custom properties just add some shading
  • In the Axes
    • Format=”C0″ – so dollar values on axis have no decimals
    • YAxisType=”Secondary” – on the series containing the sum to get count and sum on different axes
    • IsReversed=”True” – on the X axis so it is alphabetical from the top, not the bottom

A full sample can be found below with these changes included.

As a note, charting on N:N relationships also works on Marketing Lists (static only). That means you can create a list of users with a chart of how many marketing lists they are associated with. However, you will need to use a metadata browser to get the names of the intersect table (listmember) and its id field (entityid), which is different in this case.

Thank you for reading. Please sign up for the newsletter to stay up to date on new blog posts and follow me on Twitter

Sample chart xml for count and sum of opportunities per competitor

Here’s a sample chart xml ready for import to the competitor entity. It is made in an environment with no customizations so it should be easy to import. As always, samples are provided for fun only. Do not use in a production environment without proper testing.

<visualization>
  <visualizationid></visualizationid>
  <name>Opportunities per Competitor - by CRM Chart Guy</name>
  <primaryentitytypecode>competitor</primaryentitytypecode>
  <datadescription>
    <datadefinition>
      <fetchcollection>
        <fetch mapping="logical" aggregate="true">
          <entity name="competitor">
            <link-entity name="opportunitycompetitors" from="competitorid" to="competitorid">
              <link-entity name="opportunity" from="opportunityid" to="opportunityid">
                <filter type="and">
                  <condition attribute="statecode" operator="eq" value="0" />
                </filter>
                <attribute alias="CountOfOpportunities" name="opportunityid" aggregate="count" />
                <attribute alias="EstimatedRevenue" name="estimatedvalue" aggregate="sum" />
              </link-entity>
            </link-entity>
            <attribute groupby="true" alias="GroupBy" name="competitorid" />
          </entity>
        </fetch>
      </fetchcollection>
      <categorycollection>
        <category alias="GroupBy">
          <measurecollection>
            <measure alias="CountOfOpportunities" />
          </measurecollection>
          <measurecollection>
            <measure alias="EstimatedRevenue" />
          </measurecollection>
        </category>
      </categorycollection>
    </datadefinition>
  </datadescription>
  <presentationdescription>
    <Chart Palette="None" PaletteCustomColors="91,151,213; 237,125,49; 160,116,166; 255,192,0; 68,114,196; 112,173,71; 37,94,145; 158,72,14; 117,55,125; 153,115,0; 38,68,120; 67,104,43; 124,175,221; 241,151,90; 186,144,192; 255,205,51; 105,142,208; 140,193,104; 50,125,194; 210,96,18; 150,83,159; 204,154,0; 51,90,161; 90,138,57;">
      <Series>
        <Series ChartType="Bar" IsValueShownAsLabel="True" Font="{0}, 9.5px" LabelForeColor="59, 59, 59" CustomProperties="DrawingStyle=Cylinder, PointWidth=0.75, MaxPixelPointWidth=40">
          <SmartLabelStyle Enabled="True" />
        </Series>
        <Series ChartType="Bar" IsValueShownAsLabel="True" LabelFormat="C0" Font="{0}, 9.5px" LabelForeColor="59, 59, 59" CustomProperties="DrawingStyle=Cylinder, PointWidth=0.75, MaxPixelPointWidth=40" YAxisType="Secondary">
          <SmartLabelStyle Enabled="True" />
        </Series>
      </Series>
      <ChartAreas>
        <ChartArea BorderColor="White" BorderDashStyle="Solid">
          <AxisY LabelAutoFitMinFontSize="8" TitleForeColor="59, 59, 59" TitleFont="{0}, 10.5px" LineColor="165, 172, 181" IntervalAutoMode="VariableCount">
            <MajorGrid LineColor="239, 242, 246" />
            <MajorTickMark LineColor="165, 172, 181" />
            <LabelStyle Font="{0}, 10.5px" ForeColor="59, 59, 59" />
          </AxisY>
          <AxisX LabelAutoFitMinFontSize="8" IsReversed="True" TitleForeColor="59, 59, 59" TitleFont="{0}, 10.5px" LineColor="165, 172, 181" IntervalAutoMode="VariableCount">
            <MajorTickMark LineColor="165, 172, 181" />
            <MajorGrid LineColor="Transparent" />
            <LabelStyle Font="{0}, 10.5px" ForeColor="59, 59, 59" />
          </AxisX>
          <AxisY2 LabelAutoFitMinFontSize="8" TitleForeColor="59, 59, 59" TitleFont="{0}, 10.5px" LineColor="165, 172, 181" IntervalAutoMode="VariableCount">
            <MajorGrid LineColor="239, 242, 246" />
            <MajorTickMark LineColor="165, 172, 181" />
            <LabelStyle Font="{0}, 10.5px" Format="C0" ForeColor="59, 59, 59" />
          </AxisY2>
        </ChartArea>
      </ChartAreas>
      <Titles>
        <Title Alignment="TopLeft" DockingOffset="-3" Font="{0}, 13px" ForeColor="59, 59, 59"></Title>
      </Titles>
    </Chart>
  </presentationdescription>
  <isdefault>false</isdefault>
</visualization>

If you made it this far. You’re awesome! Seriously. Tweet about it!

9 Comments