MS Dynamics 2016 new Web API: So, what do we do now?

As you may already know, MS Dynamics CRM 2016 comes with a new API for web development, and even a new endpoint has been implemented. So, for all of us who had developed resources using the old API, does that mean that we need to rush into a massive refactoring crusade? Well, not for the moment since the old (CRM2011) endpoint is still available, and hopefully will be supported for the near future.

This article won’t be a summary of the new features in the new API, you can find plenty of material on the topic. A good starter can be found here. However, I wanted to provide a side to side comparison of the main syntactical differences between the new and old APIs, for which I have created a very simple web-resource. As a bonus, I made this web-resource backwards-compatible which proves useful if you have to maintain the same code-base for multiple versions of Dynamics CRM.

The sample shown next is for a very simple HTML web resource that displays all the active system views in the organization, sorted in alphabetical order.

Differences

  1. As I mentioned before, the endpoints are different; however, the server url remains the same.
    Old Suffix: "/XRMServices/2011/OrganizationData.svc/"
    New Suffix: "/api/data/v8.0/"
  2. Entity and field names no longer need to match the exact casing defined in the schema names. Also, for entities we no longer need to use a combination “Entity”+”Set”, we just need to use the plural name for the entity.
    Old Entity Format: SavedQuerySet
    New Entity Format: savedqueries
  3. The syntax for filters on complex data types like EntityReference or OptionSet is different.
    Old format: filter=StateCode/Value eq 0
    New format: filter=statecode eq 0
  4. The old page size is 50, whereas, the Web API allows you to set the page size, which in turn can improve performance by reducing the number of trips to SQL server.
    New syntax for setting page size: setRequestHeader("Prefer", "odata.maxpagesize=100")
  5. The syntax to verify whether there’s more data to fetch is also slightly different.
    Old syntax: __next != null
    New syntax: @odata.nextLink != null

Final thoughts

If you are implementing web resources for Dynamics CRM 2016, you can still use the old API; however, it’s definitely a good idea to start using the new web API since the functionality offered is richer and brings the opportunity to develop components that perform faster.

HTML markup:

<html>
<head>
 <title>Sample: Show All System Views</title>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 < script src="ClientGlobalContext.js.aspx"></script>
 < script src="bpi_testwebapi.js" type="text/javascript"></script>
 <meta>
 <meta>
</head>
<body style="word-wrap: break-word;">
 < div style="margin-right: 8px; margin-left: 13px;">
 <ol id="systemViews">
 </ol>
 </div>
 < script type="text/javascript">Setup();</script>
</body>
</html>

Supporting JavaScript:

function Setup() {
 var filterExpression = "savedqueries?$select=name,savedqueryid&$filter=statecode eq 0&$orderby=name asc";
 var url = getClientUrl() + "/api/data/v8.0/";
 var qry = url + filterExpression;
 RetieveData(qry);
}

function Setup_Pre2016() {
 var filterExpression = "SavedQuerySet?$select=Name,SavedQueryId&$filter=StateCode/Value eq 0&$orderby=Name asc";
 var url = getClientUrl() + "/XRMServices/2011/OrganizationData.svc/";
 var qry = url + filterExpression;
 RetieveData_Pre2016(qry);

}

function RetieveData(url) {
 var req = new XMLHttpRequest()
 req.open("GET", encodeURI(url), true);
 req.setRequestHeader("Accept", "application/json");
 req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
 req.setRequestHeader("OData-MaxVersion", "4.0");
 req.setRequestHeader("OData-Version", "4.0");
 req.setRequestHeader("Prefer", "odata.include-annotations=\"OData.Community.Display.V1.FormattedValue\"");
 req.setRequestHeader("Prefer", "odata.maxpagesize=100");
 req.onreadystatechange = function () {
 if (this.readyState == 4 /* complete */) {
 req.onreadystatechange = null;
 switch (this.status) {
 case 200:
 var result = JSON.parse(this.response);
 // browse thru all results and build html
 var values = result.value;// type array 

 for (i = 0; i < values.length; i++) {
 addNewView(values[i].name);
 }
 if (result["@odata.nextLink"] != null) {
 //
 RetieveData(decodeURI(result["@odata.nextLink"]));
 }
 break;
 case 503:
 // service not available - we need to call the pre-2016 endpoint
 Setup_Pre2016();
 break;
 default:
 var error = JSON.parse(this.response).error;
 alert(error.message);
 break;
 }

 }
 };
 req.send();
}

function RetieveData_Pre2016(url) {
 var retrieveReq = new XMLHttpRequest();
 retrieveReq.open("GET", url, false);
 retrieveReq.setRequestHeader("Accept", "application/json");
 retrieveReq.setRequestHeader("Content-Type", "application/json; charset=utf-8");
 retrieveReq.onreadystatechange = function () {
 if (retrieveReq.readyState == 4) {
 // complete
 //
 var retrieved = JSON.parse(retrieveReq.responseText).d;
 //
 for (var i = 0; i < retrieved.results.length; i++) {

 addNewView(retrieved.results[i]["Name"]);
 
 }
 // Check if there are more records to fetch
 if (retrieved.__next != null) {
 RetieveData_Pre2016(retrieved.__next)
 }
 }
 };
 retrieveReq.send();
}

function getClientUrl() {
 //Get the organization URL
 if (typeof GetGlobalContext == "function" &&
 typeof GetGlobalContext().getClientUrl == "function") {
 return GetGlobalContext().getClientUrl();
 }
 else {
 //If GetGlobalContext is not defined check for Xrm.Page.context;
 if (typeof Xrm != "undefined" &&
 typeof Xrm.Page != "undefined" &&
 typeof Xrm.Page.context != "undefined" &&
 typeof Xrm.Page.context.getClientUrl == "function") {
 try {
 return Xrm.Page.context.getClientUrl();
 } catch (e) {
 throw new Error("Xrm.Page.context.getClientUrl is not available.");
 }
 }
 else { throw new Error("Context is not available."); }
 }
}

function addNewView(viewName) {
 var newLine = document.createElement("LI");
 newLine.appendChild(document.createTextNode(viewName));
 document.getElementById("systemViews").appendChild(newLine);
}

 

 

 

 

 

Advertisement

Why You Need The Cloud

You use the cloud more than you realize. Did you write a postcard today? How about writing a check? What about going to the post office? Do you even know where your post office is? Has anyone used a map today; the paper kind?

Five years ago 53% of people would have answered yes to at least 2 or 3 of these questions. The cloud is changing the world we live in and the future ahead. We know we live in a world of social media. We live in a world of mobile. We live a world of analytics. We also live in a world, in this amazing time, called cloud. Cloud is something that is going to transform the way all of us work. In fact, it already is. If you have kids, you’ve either thought about or actually monitor what they do on their mobile devices. That’s a good thing these days, right? We’re in a world in which everything is connected. Let’s take a little journey on the connected world.

Fascinating Facts

In 1960, the population of planet Earth was 3 billion. Today, you likely have a phone where you can look that up on Google or you can ask Siri or Cortana? These answers are easy to find. We’re in a connected world that uses the cloud. The population of the planet today is 7.1 billion. The population in 2020 will be 7.8 billion. This is really interesting because the thing about cloud is not about the number of businesses. It’s about the number of people. What do you think the population of the United States was in 1960? It was 180 million, right? The population of the US today is 316 million. That’s almost double and continues to grow. It continues to grow where you live; in big cities like LA, NY, Chicago, Atlanta, and Miami. Cities are getting bigger and bigger so there’s more and more people to serve in those cities. Let me give you another example. The population of China in 1960 was 660 million. Now it is a staggering 1.35 billion. That’s the latest census statistics. That’s a lot of people. Can you imagine how many cloud consumers are going to be added in China? The population of India in 1960 was 449 million. Today, it is a staggering 1.25 billion. It’s gone up “3X”. The cloud is about the users. Let me give you one last statistic to give you a sense of the magnitude of the journey that you’re on and why it’s important that you take that journey soon. 20 years ago, there were less than 500 million cell phone subscribers. Today, worldwide, there are 6.7 billion cell phone users. Many people have more than one subscription. As of this year (2015), there are 4.5 billion users. That means that most of the people on the planet already has a cell phone. Everything is connected. Data flows everywhere in the world.   Excerpts from: Nimish Dave, Ingram Micro Cloud Summit 2015 Keynote.

Opportunity Knocks

As the number of people accessing data on their devices and apps increases, organizations already in the cloud are experiencing a transformation of efficiency, cost and emergence which allows small businesses to compete with major firms for business.  Not only do these cloud adopters experience the benefits but their consumer base does as well. Some great examples are Airbnb and Uber.  As a consumer, these cloud offerings weren’t there a few years ago.  However, they are now.  Plus they have added efficiencies to our everyday lives.  As this trend continues, your employees and consumers expect it.  Imagine that you’re a medical association with 25,000 members.   Your consumers, the medical professionals, can go onto a mobile app to register for an industry event that they get Continuing

Medical Education (CME) credit at. Within that app they can register and track events hosted by you, another society, other journals, grand rounds, and virtually anything that counts for credit. Now imagine if upon registering, you and other credentialing bodies could see and track their transcripts across organizations. Imagine as the medical professional being able to do this from one app rather than disparate places to understand what their entire CME transcript is and what categories have not been satisfied and when those are due.

When is the last time you’ve traveled? If you’ve traveled recently, you likely have used a mobile cloud app like the one United Airlines offers. In there, you can purchase your tickets, pick your seats, add extra bags, track your miles, view your travel history, receive status updates and board the plane all from your phone.

As consumers, we expect the same conveniences in our professional lives as we do in our personal ones. The first step toward achieving this goal is getting your organization on to the cloud so that the transformation process can begin. Once you’re in the cloud, your users and consumers can use any device, any platform, anywhere which opens up new opportunities.

Challenges In 2015

Many small and medium sized businesses (SMB) are focused on increasing profitability, growth and customer relationships while reducing operational costs. Below, the SMB top 10 business issues, IT priorities and challenges businesses are faced with are depicted. Source: 2015 Top 10 SMB Business Issues, IT Priorities and IT Challenges (Infographic).

top-ten-SMB-Issues-priorities-challenges

Ways Others Are Using It

Many SMBs are leveraging the cloud more than ever. The following infographic depicts the current trends on how it is being used. Source: Intuit, The Applification of Small Businesses.

IntuitSMBcloudStats2015

What Others Are Doing About It

Here are the current statistics as more businesses continue to adopt the cloud. The infographic below shows who is adopting the cloud, how SMBs compare to larger businesses, the realized benefits, top uses, the future and projections. Source: Rackspace.

cloudstats-2015

Is The Cloud In Your Roadmap?

As SMBs continue to adopt the cloud at an accelerated rate, they’re enabled to focus on their customers and making their businesses operate efficiently, timely and smart. Think about your competitors. Have they adopted the cloud yet? Whoever adopts earlier will have a competitive advantage in reaching new markets and growing existing ones. Is the cloud in your business roadmap? Don’t get left behind in this amazing time.

About Us

BusiPlanIT is a cloud market innovator helping companies who are looking for guidance on how to successfully achieve their business goals in the cloud. We offer services developing roadmaps and strategies, cloud procurement and implementation as well as enterprise technology transformation.

For a free cloud assessment, contact us contact us today.

8 Benefits You Should Expect Of CRM

If you’re currently using Dynamics CRM or shopping around, you’ll want to read this important message.

Does your CRM increase the productivity of your workforce?

A correctly aligned CRM can enable your workforce to operate 10% to 30% more efficient.

“On average, sales and marketing costs average from 15%-35% of total corporate costs. So the effort to automate for more sales efficiency is absolutely essential. In cases reviewed, sales increases due to advanced CRM technology have ranged from 10% to more than 30%.” –Harvard Business Review

Is your CRM preventing disruptions in your sales cycle?

A common complaint we hear among the CRM user community is how their CRM doesn’t really align with their sales methodology. You do not have to conform to CRM. CRM can conform to your way of doing business.

Can you easily identify new market opportunities by simply analyzing the data patterns that reside in CRM?

A well designed CRM captures the right information and has usable and intelligent analytic capabilities that business leaders and decision makers can act on in a timely manner. It creates a competitive advantage when you can, for instance, identify when to upsell items because you can see a pattern that would otherwise have gone unnoticed. You’ve now captured revenue you would have missed out on.

“Successful CRM is about competing in the relationship dimension. Not as an alternative to having a competitive product or reasonable price- but as a differentiator. If your competitors are doing the same thing you are (as they generally are), product and price won’t give you a long-term, sustainable competitive advantage. But if you can get an edge based on how customers feel about your company, it’s a much stickier–sustainable–relationship over the long haul.” –Bob Thompson, CustomerThink Corporation

Does your CRM enable you to define marketing strategies and lead tracking that are truly necessary for your organization to be effective?

One of the most important pieces to the lifeblood of successful businesses is market penetration and growth. If your CRM isn’t flexible enough to allow you to market and track your potential customers in an effective and efficient manner, you’re losing potential revenue.

Is your CRM growing with your business?

We’ve seen businesses that have aligned their CRM with their business model grow faster than ones who haven’t.

Is your CRM saving your workforce time?

When CRM is tailored to your business, your workforce becomes more productive with the time saved from too many clicks, steps or the way data is organized in out of the box CRM.

“The impact on an organization can at times be subtle and distributed throughout the enterprise…Cost savings and productivity enhancements can be seen in saving a sales person 20 minutes per week in writing activity reports, or answering four times the volume of web-based service requests in the same amount of time.” –Mary Wardley, vice-president of IDC’s CRM applications research.

Does your CRM create value for your organization?

We’ve all heard the term that IT systems are typically a “cost center”. CRM on the other hand can actually generate revenue opportunities and efficiencies that in turn more than pay for the investment.

Do you have a 360 degree view of your customers?

One of the most important reasons organizations like yours invests in CRM is to have the ability to have all the data about their customers in a consolidated view which tells their story so that you don’t have to guess or burn precious time tracking down fragments of information in order to nurture that relationship more personally.

If you answered “No” to any of these questions, then you’re not alone. Many are not benefiting from the full value their CRM has to offer but could be.

The solution to maximizing the power that CRM can have on your organization is BusiPlanIT. We specialize in tailored Dynamics CRM solutions that maximize value. Let’s face it. Out of the box capabilities can only get your CRM part of the way to truly aligning with your business model. Why not close that gap and experience the full potential Dynamics CRM can give your organization.

For a free assessment, contact us today. Please leave your preferred phone number & email address in the question box as well as any other helpful info.

W: www.busiplanit.com

A free customizable Editable Grid for Dynamics CRM 2015/2016/365/Unified Interface!

UPDATE 01/01/2020: We are still alive and have released a new version! We have updated our solution to work with Dynamics 365 Unified Interface.  Please download the solution below for the enhancement.  

UPDATE 08/01/2017: We have enhanced our grid again!  The latest version includes performance enhancements and exciting new features!  We have added the ability to add CUSTOM RIBBON BUTTONS!!  Haven’t you missed them since CRM 2011??  Custom ribbon buttons can call custom JavaScript functions to take actions.  We have also enhanced our JavaScript extensions by adding in validation events and events for onsave. Please email EditableGrid@Microplanit.com for documentation. 

UPDATE 03/15/2017: We have released a new version!  The latest version includes performance enhancements and new features!  We now allow the grid to be extended by custom JavaScript, Import data to the grid by csv (text, boolean, date, decimal, double, integer, memo, and money FieldTypes), Keep header static on scroll, CASCADE GRID LOOKUPS, Custom FetchXML for lookup filtering, ability to position ribbon buttons, and some minor bug fixes. 

UPDATE 06/17/2016: We have enhanced the grid by adding Hierarchical (drill down) grids.  This configuration item is available only for our clients that have purchased a license.  We have also created the ability to add default values to record columns when new row is created (available in our free version as well). 

If you would like to get a copy of the solution, just send us a request at: http://www.microplanit.com/contactus.aspx?p=Free Tools: Editable Grid.  You will receive an email with a download link to the Dynamics CRM Editable Grid solution.

AccountDrillDown

UPDATE 02/26/2016:  We have dropped support for CRM 2013.  If a solution is needed for CRM 2013 please email us at editablegrid@microplanit.com. We have also added additional items such as AUTO SAVE / BULK SAVE, GRID COLUMN SORTING, IN LINE NEW ROW (This will create a new record in CRM from the grid), AND  DELETING RECORDS FROM GRID!

How many times have you heard “This grid is great, but I hate double clicking and going into the record to edit it, then going back to my record.”  I certainly have heard it many times from many clients.  In fact I feel the same way sometimes.  It gets really annoying that you have to go into each record and change one attribute.  Why can’t MSFT build this into the system?  It’s not hard…well maybe it is.

At BusiPlanIT labs, we have done the hard work for you and come up with a solution that leverages JQuery js, JQuery UI js, and SlickGrids js.  We have created a full HTML5 solution for you that works in CRM 2013, 2015, 2016, and 365.  Oh and let’s not forget the different browsers!  It works on Chrome, Internet Explorer, and Firefox.

We are offering one free grid for any use in the CRM.  You can place it in anywhere that loads web resources such as a dashboard or on an entity (OOTB or custom) form.  The grid can handle showing all records or just related/regarding records.  If you are interested in getting more than one grid, contact me, my information is at the bottom of this post.

In our example we will show related contacts to an account record.  Although this can be configured for any record, we will show a grid that everyone can relate to.

Below are instructions (with pictures) on how to configure it and use it for related contact on an account form.

Pre configuration step:  Install the BusiPlanITEditableGrid solution from the download link at the bottom. 

  1. Since every grid needs a view, we will need to create one. We decided that instead of piggy backing on system and personal views, let’s have users do an advance find view and place the FetchXML into our solution.  This allows us to do a little more complex views if needed.  Also doesn’t require our users to create specific views that muddy up the entity view drop down list.Go ahead and open Advance find.
    pic1
  1. Select the record types you want to see (contacts) and apply a filter. You can filter as deep as you want.  For this example I want to just show active contacts on my account record.
    pic2
  1. Pick the columns you want to see in the Grid. There is no column number limit.  Do not select the composite fields (Address and FullName) they are not editable in the grid.  Status field (status and status reason) will show up on the grid, but are not editable either.  Do not worry about the order we will set that later.pic3
  1. In order to sort, configure the sorting options. For this grid I want the contacts sorted by First Name.
  2. Run the advance find query, if it looks okay then you can proceed to the next step. If something needs to change, revisit the previous steps.  Remember this query will return all contacts in the system.   You do not need to filter the related account, we will do that configuration later.  Also, if you want, you can save this advance find view as a personal view, just in case you want to change it later.
  3. Download the FetchXML and save it.
  4. Now we want to create a new Editable Grid View Configuration record. You can get to this by Dashboards – > BusiPlanIT Editable Grid View Configurations -> + (New) or  doing an advance find, querying for Editable Grid view configuration, and clicking create new record.  I chose to go to the dashboard since it’s a little faster.  We actually created a dashboard in our managed solution for easy access!pic4pic5
  1. Fill out the required fields
    1. Name – Name of the record. This can be anything.  For this example I’ll choose “Related Contacts on Accounts”
    2. Entity to display on – This is the entity you want to display the grid on. For this example we are using Account.
    3. ID – This is the ID that we will use to determine which grid to display. If you have multiple versions of this grid, IDs will be different for each grid record.  Since this is a demo use the number 1.
    4. Max Record per page – This can be any number from 10 – 300.  However for a subgrid on a form I’ve noticed that 10 works best.
    5. GRID XML – From the advance find downloaded fetchxml, copy the text and place it into this field.pic6
  2. Click Save and watch the magic happen!  Our fancy plugin will parse through the fetchxml and pull out all the attributes that need to be displayed, and also will give you a list of relationship to pick from to show related/regarding records.
    pic7
  • Do not manually create or delete attribute records, the plugin creates it and keeps it in sync with the fetchxml.
  1. If the order of the attributes is incorrect (The way it currently display is the left most column is supervisor and the right most column is description), we have a few options:
    1. Make “Automatically Order Attributes” to yes, and you can adjust the fetchxml, the order will be taken from first attribute name listed in the xml. Save the record after the fetchxml is adjusted, and the order will automatically reorder.
    2. If you do not want to modify the fetchxml change “Automatically Order Attributes” to No, save the record and change the display order for each attribute record to your liking.In this example I choose to do option “b”.
      pic8
  1. Additionally the display name and width can also be adjusted. In my example I wanted to rename Mobile Phone to Cell Phone, it can be done.I went ahead and adjusted the width and names.  Just a reminder you can do this anytime, it does not have to be now.
    pic9
  1. If we want to only display related records place a check mark under “Display Only Related Records”pic10
  1. A drop down next to it will appear “Related Relationship” Very similar to how sub grids are in CRM you must pick the relationship you want show in the grid.  For this example I want to show all contacts on the account that have the same parentcustomerid (Company Name) as the account record I’m on.pic11
  1. Save the record and remember the ID number you picked.
  1. Since I am placing this grid on an account form. I will go over the customizations and edit the account form:
  1. I went ahead and created a new tab on the form, but really the grid can be placed anywhere you want.pic12
  2. Inside the tab I will insert a HTML Web Resource
    1. Web Resource* – type “BusiPlanIT Editable Grid” or “bpi_busiplaniteditablegrid”
    2. Name – Can be anything I picked busiplanitgrid1
    3. Label – pick a good identifier for the grid, I picked Related Contacts and checked “Display label on the form”
    4. In the Web Resource Properties (custom parameter [data]) you must enter the ID of view configuration record we just customized. In my example it was the number 1
      pic13
    5. Before you click okay, go to the formatting tab. This will make sure the grid looks good on the form
      1. Number of rows – what I normally do is add 5 to the “Max records per page” we picked.  In my example the Max Records per page was 10.  So I put 15
      2. Scrolling – As necessary
      3. Display border – I uncheck this so the grid looks like it belongs on the form.pic14
  1. Click Okay, save and publish the form. You are ready to see the grid in action!

Go to any account and the Grid should be in the location where you placed the web resource

pic15

Clicking into (sometimes double click, if you are not focused on the gird) the field opens it up for edit.

Using the Editable Grid:

For users that are not system admins we have created Security roles to append their teams or user record.

Editable Grid User – User role that allows users to only view and user the grid

Editable Grid Customizer – User role that allows a system customizer to customize and modify the grid configuration settings.

Limitations:

  1. If the fetxchml is complex and you are returning columns from child records, those records will show up in the grid, but will not be editable.
  2. Deleting a record from the Grid is not possible in this version
  3. Many to Many related relationship do not show in the related drop down list. But it can still be done by manually modifying the XML.  Reach out to me and I will help you.  In the future we will add Many to Many relationships to the drop down.
  4. Status and Status reason cannot be edited in the grid
  5. If displayed on dashboard, double scroll bars may appear for vertical scrolling (depending on record size and page size).

Text /decimals/money fields – clicking into the field opens an editable text box once you click away from the field, the value will be saved

pic16

Look up field types – Clicking into the look up field will bring it into edit mode.  You can begin typing and filtered list will show top 50 results from the CRM based on StartsWith.

pic17

If you cannot find the correct look up click on “Look Up More Records” will pop open the CRM look up search, where you can select a view or for complex look up types a different entity.

pic18

MultiLine text fields – Click into the field will bring up a long text editor.  To save changed press the save button.

pic19

Date Fields – Date fields are handled the same way a CRM date field is handled.  Clicking into the field allows the user to type a date (date must be in format mm/dd/yyyy) or select a calendar to view a date.

pic20

OptionSet Fields –  work the same way CRM does drop downs.

Opening a record –  On the left most column is a check box.  Double clicking this will open the record in a new window.  You can also right click on the grid and go to open new window as well

doubleclick

Creating a new record – In the top right, above the grid is a plus sign.  This plus sign works the same way an OOTB grid does in creating a new record.  If you have 2015 SP1 the editable grid view configuration record has a drop down to enable the quick create form.  Set that option to yes if desired.

pic22

In our latest release we have added the ability to create a NEW ROW and save the row to create a new record

These are the configuration sets that should get you on your way in:

  1.  Auto Save = No (this will give you a save button on the grid to do bulk saves and also enables other features)
  2. Display Add New Row = Yes (Adds new row button to the grid, were you can add your opportunity products)
  3. Refresh Grid After Save = Yes

newrow

Grid Menu – By right clicking anywhere on the grid, brings up a small menu.  From this list you can open a record, email a link for a record, or refresh the grid.

 pic23

Navigating the grid – By pressing the tab key you can go to the next cell.  The arrow keys will also allow you to move from cell to cell.

 

If you are interested in getting more than one Editable Grid added on to your CRM please contact us at editablegrid@microplanit.com. We are finalizing our licensing model and will get back to you with options.  Stay tuned for new enhancement and updates, as we are constantly enhancing our editable grid with new features!

If you have any bugs or issues please email me at editablegrid@microplanit.com.

If you would like to get a copy of the solution, just send us a request at: http://www.microplanit.com/contactus.aspx?p=Free Tools: Editable Grid. You will receive an email with a download link.

DISCLAIMER THIS TOOL IS PROVIDED BY MICROPLANIT LLC. “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANT ABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MICROPLANIT LLC. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Errors in Goal Recalculation

Platform: Dynamics CRM 2013 On-Premise SP1

Entity: SalesOrderDetail

Goal Metric: Extended Amount (sum)

Rollup Query: Product Group

Time Range: Custom

Symptom: Goal Progress totals are inaccurate (when two or more records have the same extended amount, product group and creation date.)

I noticed that after recalculating the above mentioned goal, the resulting progress total amount was inaccurate.  Started a SQL profile, and found out that the supporting SQL statement, yields less results than a direct query.

A direct query like the following one yields 82 rows:sqlok

However, the SQL generated by the goal recalculation yields less records:sql_Union

If we look at the first few rows in both result sets, we realize that since the goal recalculation uses a UNION statement, it excludes records with the same information (thinking that they are duplicates). For example, the first sales order has 2 lines with basically the same data (amount 46.51), but in the second set, we appreciate that only one is accounted for.

The problem happens when you have 2 or more salesorderdetail records with the same “extended amount” and the same product group. Since your SQL script uses a UNION statement, it thinks that those records are duplicates. The goal recalculation SQL statement fetches the following columns:

ExtendedAmount, new_productgroupid, ownerid, createdon, ownerbusinessunit, salesorderid

I am not sure why doesn’t it fetch salesorderdetailid (the primary key), which would resolve the problem in the recalculation.

The MSFT Dynamics CRM product team needs to look into this.

Is Goal Recalculation Time-zone Independent? Well, maybe not.

One of the nice features in Dynamics CRM when it comes to dates, is that it stores everything in Universal Time. For the most part, this works pretty well until you run in the following scenario related to goal recalculation.

Let’s suppose you have teams of salespeople grouped by regions, and that you have members in those teams that have goals not tied to any direct sales but goals assigned to the entire team, for example administrative staff. In this scenario, you would create goals with the following characteristics:

  • Goal Metric: Amount of Sales
  • Goal Owner: Admin staff
  • Target: Fixed Dollar Amount
  • From: Fixed Date
  • To: Fixed Date
  • Rollup Only from Child Goals: No
  • Record Set for Rollup: All (sales records owned by all team members)
  • Rollup Query: A query to filter by region

In this case, the expectation would be that all administrative staff shows the same progress at any moment. Well, at least that’s what I thought until I looked at the following chart:

goals

Figure 1 – Goal Progress Chart

It’s obvious that the progress for the first member is different from all others. After verifying that all the goals were exactly the same and have been recalculated around the same time, I was running out of ideas.

Fortunately, this is a CRM on premise implementation, so I had more chances to look at the server at a deeper level. The CRM async service was running OK, and no errors were found in the event log or CRM trace.

So I needed to dig even deeper. I ran a SQL Profiler session, and decided to recalculate the goals for the first and second person in the team. After a few hours of research, I found the smoking gun:

Person_Central

Figure 2 – Excerpt query person 1

Person_EST

Figure 3 – Excerpt query person 2

It turns out that person 1 had his time-zone set for Central Standard Time, whereas person 2 had his time-zone set for Eastern Standard Time; therefore, the query for person 1 was missing all transactions for the first day in the time range, given that all sales data only records the date of the transaction and the data is imported using Eastern time.

Now that I found this, at least I know what caused the discrepancy, and the fix is as simple as making every team member use the same time-zone. However, that may not be a realistic scenario. You could perfectly have teams that have members across different time-zones, in which case the goal recalculation should really be time-zone agnostic. That’s up for debate or perhaps to have the Dynamics product team take a look at.

Another Handy Tool Compliments of BusiPlanIT: Email to a Team

How many times have you heard, “Why can’t I email a Team in CRM”? Since Dynamics CRM uses Activity Parties, the Team option is not available. When creating a Workflow, the User must manually select all of the Users that are members of the Team and add them to the “To” field in the Email template. Who wants to do that??? What happens when members of the Team change?

At BusiPlanIT Labs, we have released another handy tool that leverages Custom Workflow Activities in CRM to solve this common challenge. This Custom Workflow Activity works in CRM Online and On-Premise for CRM 2011, CRM 2013, and CRM 2015. Users must have email capabilities set up in CRM either through the Outlook Client, Email Router, or Email Server Side Sync in order for emails generated by the Workflow to be sent out.

The solution is very simple. It has one component.

  • Custom Workflow Activity (BPI_FreeEmailToTeam)

The Custom Workflow Activity can be used in any workflow process. One example is when a Contact is created or updated an email is to be sent out to a Team. Below are the details on how to use this useful Custom Workflow Activity in a Workflow:

Pre Workflow setup – Install the BusiPlanIT EmailToTeam solution from the download link at the bottom.

  1. Create a new Workflow Process.
    emailtoteam1
  2. The Workflow can be used on-demand or by automatic operation (when a record is created/assigned/updated/etc…).
    emailtoteam2
  3. The first step is to add “Create Record” with entity = “Email”.
    emailtoteam3
  4. Next click “Set Properties” and the E-mail form will pop up. Set the contents for “From”, “Subject”, and “Body”. “CC”, “BCC” and “Regarding” are optional. Remember to keep “To” empty so that this email will get sent to a Team. The “To” will get dynamically populated with the members of the Team during the execution of the Workflow.
    emailtoteam4
  5.  Add a new Custom Workflow Step “BPI_FreeEmailToTeam. BPI_FreeEmailToTeam”.
    emailtoteam5emailtoteam6
  6. Once the Custom Workflow Activity step is added. Select “Set Properties”. This will allow you to configure which Team to send to and whether the email should be sent automatically.
    emailtoteam7
  •  Email you wish to update – This is the email we created in the first step. The members of the Team will be appended to the “TO” of this email
  • Team to Add TO – this will be the Team that this email gets sent to.
  • Send Email – If set to “True”, the email will get sent when this Workflow is completed. If set to “false” the email does not get sent and sits in Open Activities.

7.  That’s it! Just activate your Workflow and let it run. Happy Team-mailing!

If you would like to get a copy of the solution, just send us a request at: https://www.busiplanit.com/contactus.aspx?p=Free Tools: Email to Team

DISCLAIMER THIS TOOL IS PROVIDED BY BUSIPLANIT INC. “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BUSIPLANIT INC. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Who needs a free customizable team calendar for Dynamics CRM 2013? Maybe you do.

How many times have you heard “I need to display my team’s data in a calendar view” while customizing a Dynamics CRM system? Perhaps more than once, and unless you used one of the paid components available on the market, you were out of luck.

At BusiPlanIT labs, we have come up with a solution that leverages one popular open source JQuery library (FullCalendar) and some OData calls, and embedded them in a solution that allows us to place a calendar anywhere we want in any Dynamics CRM 2013 application.

The components of this solution are:

  • JQuery library (jquery.com)
  • FullCalendar library and styling file (http://fullcalendar.io)
  • HTML page
  • JavaScript that contains OData calls to fetch your data
  • Sample dashboard

The HTML web resource can be used with any entity (OOTB or custom) and the data displayed is sorted by a date field passed in the custom parameters. In addition, you can pass an OData filter and a team name for further filtering. Your data will be color coded, green for active and red for inactive records. Each record displayed in the calendar includes a live link, so that you can navigate directly to the corresponding detail form.

The end result will look like this:

TeamCalendar

The following image shows the configuration screen for the HTML web resource:

TeamCalendar_Setup

Note that you will need to pass a comma separated list of parameters in the format:

Parameter1,Parameter2,Parameter3,Parametr4,Parameter5

  1. Parameter1 (Required) – Entity schema name (use the exact same casing as found in the entities list)
  2. Parameter2 (Required) – Date field schema name (use the exact same casing as found in the attributes list) to sort data in calendar.
  3. Parameter3 (Required) – String field schema name (use the exact same casing as found in the attributes list) to display in the calendar.
  4. Parameter4 (Optional) – OData filter for additional filtering (example “&$filter=Community/Value eq 1” for social channel Facebook).
  5. Parametr 5 (Optional) – Team name to filter by its members.

The parameters in the provided  example “ActivityPointer,ModifiedOn,Subject,,test,” will fetch all “activities” whose members belong to the team “test“, the field to be displayed in the calendar will be the “Subject” and the cells will displayed on the last date they were modified. It’s up you to decide which date field suits your needs best; for example if you wanted to show activities by due date, then the syntax would be “ActivityPointer,ScheduledEnd,Subject,,test,“, or if you wanted to sort them by start date then you would use “ActivityPointer,ScheduledStart,Subject,,test,“. The calendar can change display modes from daily, weekly to monthly.

This free component has some limitations that will be addressed in the paid version:

  • No drag and drop
  • Only captures one date, so no data ranges are shown
  • No edits are available from within the calendar
  • Teams of type “Access” are not supported

If you want to get a copy of the solution, just send us a request at: http://busiplanit.com/contactus.aspx

DISCLAIMER
THIS TOOL IS PROVIDED BY BUSIPLANIT INC. “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BUSIPLANIT INC. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

OData Syntax and JSON

The last html web resource I wrote seemed to be another routine coding activity.  This was a simple graphical indicator to display a light based on a value in a CRM form, and a simple OData query to fetch a single value.

This time I decided to use the following syntax:

http://<servername>/xrmservices/2011/OrganizationData.svc/<Entity>
Set(guid'<guid_value>’)?$select=<list_of_fields>

The Odata query worked as expected but the web resource was not.  Nothing was displayed and no error was generated.

After several hours of research and debugging, I found out that the JSON string that was generated had the following format:

json1

This was a little bit different from what my standard parsing routine expected.  Basically, the idea was to traverse an array called “results” using this construct:

var retrievedData = new XMLHttpRequest();

retrievedData.open(“GET”, url, false);

retrievedData.setRequestHeader(“Accept”, “application/json”);

retrievedData.setRequestHeader(“Content-Type”, “application/json; charset=utf-8”);

retrievedData.onreadystatechange = function () { retrieveReqCallBack(this, destination); };

retrievedData.send();

var fetchedData = JSON.parse(retrievedData.responseText).d;

for (var i = 0; i < fetchedData.results.length; i++) {

. . . DO SOMETHING HERE

}

Looking at old web resources that fetched multiple records, the JSON string returned was like this:

json2

So, I had a smoking gun and then the fix was relatively easy. I just needed to access the attributes of the returned (single-record) dataset directly:

var dateStart = fetchedData.myAttribute;

. . . DO SOMETHING HERE

But I wasn’t happy just finding a fix to the problem.  I needed to find the root of the problem, why was the JSON string different?

The answer was in the OData syntax used.  In previous web resources I had used “filter”:

http://<servername>/xrmservices/2011/OrganizationData.svc/<Entity>Set?$filter=<key_name>/Id eq guid'{ <guid_value> }’&$select=<list_of_fields>

This syntax will fetch the same single record but it will use the equivalent to RetrieveMultiple in the SDK, which automatically wraps the fetched results in an array called “results”.

So, keep that in mind the next time you use OData, that the syntax you choose may have an impact on how the returned dataset needs to be parsed.

New Discovery URI for O365 CRM Online

The other day I was going through the process of writing a plug-in for a Microsoft Dynamics CRM Online client. When it came to connecting the Plugin Registration Tool to their online tenant it reminded me to share this piece of wisdom so that you won’t go on a wild goose chase or second guess your CRM knowledge.

Then trying to connect you must give some basic info so that the tool can authenticate to your Online tenant. Something that Microsoft hasn’t communicated very clearly to CRM Online customers is that the authentication method has changed between January and July of 2013 depending on when your tenant was scheduled to convert over to use the O365 authentication from the old Live ID method.

Now, back to the connection info. The following screen shows the connection info for the Plugin Registration Tool (also used on the Developer Toolkit for connecting to CRM Explorer; and likely other common tools). For the discovery service, you will need to change your URI from the old way when it was Live ID authentication:

OLD WAY:

old-live-id-auth-crm
If you try to perform the above, you will surely get the famous authentication failed message.  Just truncate the discovery URI as depicted and you’ll surely connect.

Note the my example below uses the un-federated domain that O365 assigns your AD when you sign up; thus the “username@org_name.onmicrosoft.com” versus if your domain is federated it would look something like “username@domain.com” for the User Name.

The following picture shows the correct discovery URI to authenticate using O365 authentication.

CORRECT WAY:

new-o365 auth-crm

Hopefully this helps save you time.  Until next time, happy CRMing.