Archive

Archive for October, 2009

Connect for Microsoft Dynamics

October 20, 2009 Leave a comment

The Microsoft Dynamics CRM team really is heads down working on the product, planning, researching, and testing. But we find time to take a look at your suggestions sent using Connect for Microsoft Dynamics. Once you have created an account, you can review existing CRM product suggestions and if your favorite one isn’t there, submit your idea.

Key to this process is creating a suggestion that has one idea in it. That way people can vote for their favorites and the one idea can be assigned to the correct team. We’ve added this as a note so that first time users don’t create a suggestion with many, many ideas that apply to different teams. I’ve highlighted the change in the screen shot below:

clip_image001

The process of looking at suggestions is taken very seriously by the team so it is an effective way to make your needs known. We have tweaked the process over the last few years to include assigning team program managers as owners of particular areas of the product. It is now working very well and even though we were able to process over 80 percent of the hundreds of suggestions for the last version of Microsoft Dynamics CRM, we expect to review 100% of the suggestions this time around.

Final note, be clear about what you are suggesting. Provide an example for us to consider. And track your suggestion to see how the review goes.

Cheers,

JaAG

Advertisements

Fine Tune your Microsoft Dynamics CRM Workflows

October 16, 2009 Leave a comment

In working through some optimization on a CRM server, I thought it would be a good idea to check the running System Jobs.  This particular CRM installation was upgraded from 1.2 to 3.0 to 4.0.  Given that, I knew there were a few workflows that needed a face lift so before diving into them, I decided to gather information. 

My first step in the process was to create an Advanced find view that returned all System Jobs where the Status Reason = Waiting, Waiting for Resources, Pausing, In Progress.  I added the columns Error Code and Message to the result set for additional information. 

The results of the query showed that there were several thousand jobs running in various states. Here is some of the information I was able to glean from the System Jobs:

Several of the jobs failed for one of the following reasons:

  • The system was not able to execute a Send E-mail step.
    • The entity record containing the e-mail address information did not have an e-mail address
  • The record used to populate the Regarding field of the e-mail was not a valid record for this use
  • The record the workflow was trying to update was in a ‘Read Only’ state
  • Timeout periods spanned multiple days
    • Workflow was in a waiting pattern but the record that the job was running against was closed

Armed with the information above, I was able to go through the workflows and re-design with them to behave more intelligently and better handle some of the data anomalies and scenarios that they would encounter. 

Those improvements included:

  • Added a Check Condition step that checks to ensure the e-mail address field contains data before all Send E-mail steps.
    • I send a notification to an internal user if the e-mail address field of the record does not contain data.  The notification instructs the user to update the record with the e-mail address and run the workflow again.
    • Added a Cancel Workflow step that follows the Send E-mail notification to the internal user.
      • This ensures that the System Job is canceled when it is not able to complete
  • Ensured all Regarding fields of E-mails generated from the System were updated with valid record types
    • Contacts, Accounts, Leads, Opportunities, Quotes, etc. are all valid record types. 
    • This step will fail if you try set the Regarding field to another Activity type like E-mail, Service Activity, etc.
    • If you are not sure if the record you are using to set the Regarding field in an e-mail is valid, you can create a CRM e-mail and click on the Regarding field to ensure the record type you are using appears in the list.
  • Added a Check Condition step that checks the record status to ensure it can be updated before the Update step.
    • Added a Cancel Workflow if the record is in a Read-Only state
  • If the timeout period spanned a few days, I added a timeout step for each day
    • Added a Check Condition step before each timeout day to check the record status
      • Added a Cancel Workflow step to cancel the workflow if the record was closed during the day

My initial goal was to see if I could identify improvements that would reduce the result set of the query by 50%.  Applying the design improvements above, I was able to reduce the result set from several thousand to several hundred and my invested time was about 8 hours of effort. 

The above is intended as an example only and the specific steps referenced may not be the optimal approach for every CRM configuration.

Enjoy!

Donna Edwards

Case Number is Just the Ticket

October 12, 2009 Leave a comment

Microsoft Dynamics CRM has a number of entities that, in addition to the record id (represented by GUID data type in the system), also contain unique text identifiers that can be automatically generated by the platform. There is a common misconception that the way these numbers are generated is cast in stone and users just have to “live with it”.

Out of the box, system administrators have somewhat limited control over the automatic generation of these numbers using Settings->Administration->Auto-Numbering dialog.

image

Quite often CRM algorithm for auto-generated numbers for these entities is acceptable, but occasionally there is a need to generate identifiers according to the pre-existing business rules or even let users to enter the numbers. The latter was just the requirement in one of our projects where we were asked to allow end-users to enter custom numbers when creating new cases.

For the case entity (called incident in the system) case numbers are stored in the attribute ticketnumber which is an nvarchar(100) field. By default, this attribute is not event on the form but is displayed in the form header after the case record is created:

image

Our first stop is Microsoft Dynamics CRM SDK information for the ticketnumber attribute:

image

 

Note that Valid for create value is Yes meaning that we can actually set this attribute when creating new record. Valid for update is set to No which tells us that, once the case record is created, it’s no longer possible to change the case number.

If we simply add ticketnumber attribute to the form, it comes up as a read-only thanks to the default script for the case form. The solution is very simple – just add the javascript code below to the form onLoad event to make sure that the field is not read-only for create and quick create forms.

var CRM_FORM_TYPE_CREATE = 1;

var CRM_FORM_TYPE_QUICKCREATE = 5;

if(crmForm.FormType == CRM_FORM_TYPE_CREATE ||

crmForm.FormType == CRM_FORM_TYPE_QUICKCREATE)

{

crmForm.all.ticketnumber.Disabled = false;

}

The result is that users can now enter custom numbers when creating cases and system will generate the number if user does not enter one.

image

Unfortunately, if users enter a case number that already exists in the system, they will receive a generic error message that does not explain what happened. One possible solution is to create a synchronous precreate plugin that would ensure that the case number entered by the user is unique and return a custom error message if it is not.

The plugin is also a solution if case numbers need to be generated automatically. In this situation plugin can detect null case numbers (i.e. nothing has been entered on the form) and generate a new number as required by the business. If plugin does not create a case number, platform code will take care of it using a built-in algorithm.

The described approach can also be used for contract and campaign entities as well. In fact, campaign entity form already contains attribute codename (labeled Campaign Code on the form) which can be entered by the user with platform code generating the value if user does not enter one. And as before, using a plugin to provide custom numbers is just the ticket.

Happy coding!

 

 

 

 

George Doubinski

Automating Field Updates

October 12, 2009 Leave a comment

Here is a simple way to calculate the value of a field based on the values of two other fields on a form using JavaScript.  The value of the field is updated whenever the value of one of the two other fields is changed.

For this example, I will use the Opportunity form.  The request is to add a custom field that shows the Total Value of the Opportunity after Discount.  I will use the following fields for reference in the example.

  • Field1 (Custom attribute) = Total_Estimated_Value
  • Field2 (Custom attribute)  = Total_Discount
  • Field3 (Standard attribute)= Est. Booking (estimatedvalue)

Steps to implement the change:

  • Create the two custom attributes that you need by going to Settings, Customization, Customize Entities, open the Opportunity Entity, select Attributes, create two new money attributes, and save the changes.
  • Open the Opportunity form and add the two fields to the form.
  • Double-click (Open) the Est. Booking field (estimatedvalue) on the form and add the following line of script to the OnChange event of the field
    crmForm.all. Total_Estimated_Value.FireOnChange();
  • Open the Total_Discount field on the form and add the same script to the OnChange event of the field
    crmForm.all.Total_Estimated_Value.FireOnChange();
  • Open the Total_Estimated_Value field on the form and add the following script to the OnChange event of the field
    crmForm.all.Total_Estimated_Value.DataValue=crmForm.all.estimatedvalue.DataValue – crmForm.all.Total_Discount.DataValue
  • Save your changes and test using the Create or Update Form feature from the Customization Tool

The end result will be that whenever the Total_Discount or Est. Booking field is updated the Total_Estimated_Value will update by subtracting the Total_Discount from the Est. Booking amount. 

Please note that this example assumes there is always a value in the Est. Booking and Discount field when one of those fields are updated.  You may have to add some additional code that first checks to see if there is a value in the Total_Discount and Est. Booking field before firing the “crmForm.all.Total_Estimated_Value.FireOnChange();” script.  If there is no value (null), then you will have to set the value to 0 (zero).  Checking and setting the default value of the fields to 0 can be done in the Form properties OnLoad event.

Cheers,

Donna Edwards

Why a DeleteRequest returns a (empty) DeleteResponse

October 12, 2009 Leave a comment

You may have noticed that when working with the Execute method of the CRM web service you always get a response, even if it doesn’t contain any data. For instance, when passing a DeleteRequest you receive a DeleteResponse. There are no properties in the DeleteResponse though.

The reason is quite simple and I’m using the same approach in many of my own web services. Consider the following classes in a web service project:

[XmlInclude(AddRequest)]
[XmlInclude(SubtractRequest)]
public abstract class Request {
public abstract Response Execute();
}

[XmlInclude(AddResponse)]
[XmlInclude(SubtractResponse)]
public abstract class Response {}

public class AddRequest : Request {
public int x;
public int y;
public override Response Execute() {
return new AddResponse { result = x+y }
}
}
public class AddResponse : Response {
public int result;
}

public class SubtractRequest : Request {
public int x;
public int y;
public override Response Execute() {
return new SubtractResponse { result = x-y }
}
}
public class SubtractResponse : Response {
public int result;
}

public class MyWebService : WebService {
public Response Execute(Request request) {
return request.Execute();
}
}

There’s only one method named “Execute” in MyWebService and you can either pass an AddRequest or a SubtractRequest. As a response you get an AddResponse or a SubtractResponse. The great thing is that you never have to touch the Execute method again and therefore the interface of your service never changes. If you need new functionality then you create new Request and Response classes.

As the Execute method returns an abstract Response object even an operation not providing results, like the CRM DeleteRequest, has to return an instance of a derived Response class. That’s the reason why you receive an empty DeleteResponse n CRM.

The concept is very easy and powerful and as said before, I have used it successfully in many implementations. If you are creating web services then consider trying it. Even if you don’t then it helps understanding CRM a bit more.

Cheers,

Michael Höhne

Data Integration – a Reporting Approach

October 12, 2009 Leave a comment

This post originated with a conversation I was having with a potential customer who was considering buying Dynamics CRM. He had been prompted by his business partner to ask about integration with a well-known accounting application. Normally, an early question in such a conversation is ‘what data integration do you want, and why ?’, and this question was indeed asked; what was unusual was that it was the potential customer who asked me, rather than the other way around.

I’m not going to be able to answer this question to my satisfaction in one post (I may well come back to it in future posts), but what I will do in this post is introduce the main potential benefits of data integration, and explain what is typically the lowest cost approach to achieve some of those benefits. Be aware that this post is mostly focused on design considerations, and is intended to give a general view on what can be done, rather than working as a specific ‘How To’ set of instructions.

Why is there a need for data integration ?

A starting point is having 2 or more systems with structured data; the different systems normally having differing scope and purpose. A common, and relatively simple, example of 2 systems is Dynamics CRM and a finance application. If one system could do everything well, then we wouldn’t need any data integration, but this is rare. In this case, Dynamics CRM can handle some finance functionality (e.g. simple invoicing), but not others (e.g. cash flow). Similarly, most finance applications have some CRM-like functionality (e.g. manage customer contact details), but not others (e.g. interaction with customers before they buy anything). So, we have 2 systems with different uses, but there is overlap between them; for example they both store data about customers, and they may well also both store product information.

Benefits of data integration

Our two systems could run completely independently of each other, but there are several potential benefits to integrating the systems in some way. For example:

1. Having a centralised view of related data which rightfully originates from different systems. An example would be an account overview that showed data that originates in CRM (current opportunities, recent cases), as well as data that from the finance application (recent payment history, credit rating)

2. Reducing manual effort (and risk of errors) from entering the same (or very similar) data into more than one system. If a Dynamics CRM user has entered information about a sales order and the products on that order, then should you require a finance user to re-enter that data into the finance application to raise an invoice?

3. Maintaining consistency of duplicated data. Here I’m referring to less volatile data, such as customer details. You would expect each system to store a customer’s address, but how do we ensure the address details are the same?

This post will concentrate on the first benefit, and how it can be achieved using a reporting approach, but first let’s consider the range of options for achieving this benefit.

Data integration options for a centralised view

There are 3 broad approaches to get a centralised view of data:

1. Leave the data in the source systems, and use a reporting mechanism such as a Reporting Services report to combine the data from these systems

2. Implement a process to copy data from one or more systems into another system, giving one system with all the data you want. For example, you could bring data from the finance application into the CRM database. Dynamics CRM has some useful attributes on the account entity (e.g. creditonhold), and you could create additional custom entities and attributes to store data such as the payment history

3. Build a data warehouse with data that is imported from each source system. I’ve included this option for completeness, but a data warehousing project is very different from a data integration project, and I won’t cover it further here.

Comparing the first two approaches above, the main advantages of the reporting option are:

  • It is invariably the easier (and hence cheaper) option to implement. The main technical work to do is to manage identifiers (see below), and understand the data structures in the different systems, and this work also has to be done to copy data. After that, designing a report is normally significantly less effort than building a robust process to copy data
  • The data displayed is always up to date, as it comes directly from the source system. Most data duplication processes have some latency within them, which may or may not be significant

Whereas the main advantages of copying data are:

  • If you copy data into another system, you have more options for searching and displaying data in that system. For example, if data in the creditonhold attribute of the CRM account record was populated you could run an Advanced Find in CRM to find all accounts on hold, but if that data were only in the finance application you don’t get the same flexibility.
  • This option makes it possible to edit, as well as view the data outside of the source system. Although this is a potential benefit to the users, it raises a lot of implications around synchronising changes and security. Allowing data editing dramatically increases the complexity, and hence cost, of the data integration work

Other factors can have an impact, but could work either way:

  • Security. I would generally prefer to manage security solely in each source system, which lends itself more to the reporting option. However, this would require users to have access to each source system, which may be a problem
  • Licensing. The reporting option may require more user licenses for one or more systems, but the data copying option may introduce the need for an External Connector license or equivalent
  • Technology to access source systems. The reporting approach is based on being able to access each system as a relational database for SQL queries, which may not always be possible

In most cases, the fact that reporting across systems is easier and cheaper is the main influence on the decision, and the rest of this post will look at how this can be achieved, starting with identifiers.

Managing identifiers

As mentioned earlier, a significant part of the main technical work for any data integration approach is the management of identifiers. It must be possible to reliably relate a record in one system to the corresponding record in another system. Each system will have one or more attributes that identify a record; for any data integration to be robust we must use identifiers that are unique within their own system, and will not change. This rules out attributes that may change, like the account name, for example.

Two common options for identifiers are:

1. Use the built-in ones of each system (every system must have a viable identifier), and store the identifier from one system in an attribute in the corresponding record in the other system. For example, when integrating Dynamics CRM and GP, we normally store the account identifier from GP (an identifier in the form A001) in a custom attribute in the CRM account record (see below for how we get it there)

2. Generate your own identifiers, such as an account number, or product code, and store them in each system (almost all relevant systems would have an appropriate attribute already for these, but you could use a custom attribute if you prefer). These identifiers could be generated within one of you systems, or outside of them. What matters is they have to be unique within each system

Once you’ve decided on your identifiers, you have to ensure they are correctly entered into each system. This should be done as part of any initial data migration process, but the main consideration relates to subsequently created records. It is important that the business process for creating new records is agreed, and adhered to; it is much easier to manage the identifiers for accounts, for instance, if you know that a new account is always created in CRM first, then in the finance package, compared to a scenario where an account could be created in the finance package, and you could not be certain if it already existed in CRM or not. Once the business process is agreed, then we can implement a mechanism to generate (if required) and store the identifiers.

Although the management of identifiers is fundamental to effective integration, it is questionable whether it is worth creating an automated process, or whether to retain a manual element to it. The reason it is questionable is that the process should only be relevant on entity creation (and deletion, if permitted), and it may be that certain entities are so rarely created that it’s not worth building an automated system. For example, if you only create a new account once a month on average then a manual approach would seem appropriate, but it wouldn’t if you had 1000 new accounts a month.

Here are a couple of examples of how we’ve managed the account identifiers between Dynamics CRM and GP for different customers with different business processes:

1. An automated system. Accounts are always created first in CRM, and never manually created in GP. To create the account record in GP, the user clicks a button on the CRM account form. This is a ISV button that calls integration code to generate a new account record in GP, reads the generated account identifier for the GP record, and stores it in a custom attribute on the CRM account entity

2. A semi-automated system. Accounts are manually created in CRM, and also manually created in GP. To link them, the user also clicks a button on the CRM account form. This is another ISV button, but this code reads account information from GP and displays to the user a list of GP accounts that are not related to CRM accounts. If the user selects an account from the list, then the GP identifier for the account is stored in a custom attribute on the CRM account entity

These are not the only options, but they were appropriate based on the business processes (in example 1 we could dictate the process, whereas in example 2 we had to adapt to existing processes) and frequency of account creation (which was relatively rare in example 2).

Before I move on, I’ll raise a few other related points that I don’t have space to cover in detail:

  • In my examples, it is perfectly reasonable for account records to exist in CRM, but not in the finance package, and this reflects most business processes. In general a CRM application will contain account records for potential customers, whereas a finance application normally only needs to store data about customers who have bought something. This is why neither example ran when an account was created in CRM
  • An entity like the product entity may be handled differently. A common approach would be to use a batch process to upload a new product catalog, complete with externally generated identifiers, rather than the ad-hoc record creation described above

Creating and displaying reports

Once the identifiers have been established, creating a common view is relatively straightforward, though again there are a couple of options:

1. Display data from one system within another system. A classic example here would be to create a reporting services report that displays data about an account from the finance system, and takes the agreed identifier in the finance system as a parameter. This report could then be displayed in an IFrame in the account form within Dynamics CRM (see http://blogs.msdn.com/crm/comments/5275605.aspx for an example of the general techniques involved in displaying reports in an IFrame in CRM)

2. Develop a report that displays data from multiple source systems. If using reporting services, the simplest option is to create a report with 2 or more data sources, one per source system. This works fine if different report elements (e.g. tables, charts) are to display data from different systems, which is most commonly the case. It is also possible to combine data from different source systems within one report element (e.g. a chart that displays amounts invoiced (from the finance system) along with projected income (from opportunities in CRM)); you can do this using the Linked Server functionality provided by SQL Server (see http://msdn.microsoft.com/en-us/library/ms188279.aspx ).

Summary

This post has covered the major considerations involved in building an effective data integration between CRM and other systems using a reporting approach, which is typically the most cost-effective approach. Most of the implementation information in this post relates to managing identifies; this was deliberate as this is the key part of any data integration.

I also covered other potential data integration benefits and approaches, and may come back to these in future posts. The information about identifiers will be equally relevant to these other approaches.

Cheers,

David Jennaway

The CRM Configurator’s Dilemma: Repurpose or Create?

October 12, 2009 Leave a comment

As you configure Microsoft Dynamics CRM, one question that frequently arises is should I create a custom entity or repurpose a system entity.  By “repurpose” I mean take an entity that is designed for one purpose and modify its fields and form to serve a different purpose.    Say you are configuring CRM for a property management company.  There are no system entities in Microsoft Dynamics CRM called “properties” or “leases,” but there are entities that are somewhat similar, such as Contracts and Opportunities.  It can be tempting to say “I’m not doing sales opportunities, let’s repurpose the opportunity as the Property entity.”  The perception is frequently that adding additional entities will complicate the configuration. 

Before you repurpose system entities, you should first consider several things:

1.  Consider the future—is there any chance that you might need the entity in the future?  Sure, you might not use sales opportunities right now, but can you say for sure that there is no chance that another department might not see what you are doing in CRM and decide that they want to use it too?  If you repurpose a system entity and later have a need for it, you will paint yourself into a corner and make it very difficult to impossible to change course down the road.

2.  Consider the overhead—While the perception is that repurposing system entities will simplify a CRM configuration, frequently the opposite is true.  In the example of the property management company that repurposes opportunities for properties, by doing so they are bringing many unnecessary fields into their property configuration, some of which cannot be removed from the form (such as price list, is revenue system calculated, and the convert to order button).  Other system entities such as campaigns, cases and contracts all have fields like subjects and date fields that can’t be removed from the form.  Sure these things can be hidden using JavaScript; however, that will add a lot of unnecessary complexity to the configuration when compared to a custom entity with only the fields and links that are necessary, and the more JavaScript you add to repurpose entities, the more things you will need to test and potentially re-do the next time you upgrade.

3.  Consider the user experience—due to the added overhead of a repurposed system entity, typically a custom entity containing only the fields and links that are necessary will be more user friendly than a repurposed system entity.  Take a simple example, like the entity icon.  Microsoft CRM does not allow you to modify the icons of system entities, so when you repurpose a system entity, your property entity will still have the standard CRM Opportunity icon.  This can be very unintuitive for users.  A custom entity, however, can have an icon of a house or office building, or whatever makes the most sense.

Simplicity in a CRM configuration is not determined by the total number of entities in the system, but rather in how they are presented (or not presented) to users.  Really no user should see every entity in the system when they log in to CRM—they should see only what is necessary for them to do their job.  Adding custom entities will not complicate their experience, especially if you remove the unused system entity links from their view.

In case you don’t know how to do this, here are some related links:

Cheers,

Joel Lindstrom