Search: SQL+Server

Controlling User Synchronization Settings

by C.R. Matín on June 2, 2011

Today’s guest blogger is MVP Joel Lindstrom, a Solutions Consultant at Customer Effective.

imageOne of the items frequently requested, especially in large deployments of Microsoft Dynamics CRM, has been the ability to control Outlook client synchronization. CRM for Outlook provides a fantastic bi-directional synchronization between CRM and Outlook for Contacts, appointments, tasks, and other activities, but in some organizations, business requirements dictate that some or all of the synchronization be disabled, or that the settings not be user modifiable.

With CRM version 4.0, there were SQL database updates that could be used to prevent some types of synchronization, but they were unsupported and could often be overridden by a user updating his CRM for Outlook settings.

Also, contact synchronization options in CRM 4 are based on the user’s local data rules. By default, when users are created, their local data rules default to contacts owned by current user. While this worked well in some situations, in many cases, this either resulted in the user’s Outlook contacts being filled with too many contacts (if they own many contacts), or the contacts that they want to have not being synchronized to their outlook contacts. While this could be fixed by updating the user’s local data rules, it was often a surprise for users who just installed the client without first making modifications to their settings.

With Microsoft Dynamics CRM 2011, Microsoft has introduced a supported method for setting synchronization setting and controlling them from a global perspective.

clip_image001First thing you will notice is that in CRM 2011 for Outlook, there are no more checkboxes to enable/disable synchronization for tasks, contacts, or appointments. Now everything is controlled through the local data rules, which are now called Outlook Filters.

Now for CRM 2011 for Outlook, you will not only see Outlook Filters for contacts, you will also see one for each activity type. These still default to the records that you own or are to which you are a party (such as appointments you are attending). However, you can now change the filter rules to change what activities synchronize to your calendar.

Imagine a sales manager who wanted to see all appointments involving someone on his team—he could update his outlook filter and include records where the owner of the appointment was on his team.

Also, if someone wanted fewer appointments or tasks to synchronize than everything owned by her, or wanted to turn off task synchronization,you can modify her filter rule for tasks, or disable it altogether.

clip_image002

Controlling Synchronization Filters

So what do you do if you want to control Outlook Filters for all of your users—say you want them to get a different set of filters than the default “my” filters, or you want to disable synchronization for contacts?

CRM 2011 introduces a new feature called filter templates. Outlook filters are stored in the SavedQuery table of the MSCRM database. Filter templates allow you to set one SavedQuery record as the default per entity, then when new users are added to the system, their data rules will reflect the default filter rules.

See this link from the CRM 2011 SDK regarding filter templates: http://msdn.microsoft.com/en-us/library/gg328205.aspx

So you could create one user, set their Outlook filters to the desired default, then set the SavedQuery.IsDefault attribute to 1 on the SavedQuery records for that user. Then subsequent users will default to these rules.

This gives system administrators much greater control over users default Outlook Filters, but what about preventing users from modifying their data rules later?

clip_image003The security roles in 2011 have been enhanced with a new privilege setting called “Manage User Synchronization Settings” located on the bottom of the Core Records of the security role definition.

If you disable this setting, users will not be able to modify their outlook filters, ensuring that your default settings go unchanged.

Keep in mind that you may not want to do this, especially if you want users to be able to control what record synch/don’t synch; however, if your business requirements dictate limiting synchronization setting modification, this is a welcome addition.

Cheers,

Joel Lindstrom



{ 0 comments }

Ruby Gem for SugarCRM: the Basics

by C.R. Matín on May 23, 2011

Editor's Note: This is the first part in a series of articles by David Sulc, co-author of the Ruby gem for SugarCRM. In this article, he details setting up and basic usage of the gem. Stay tuned for part 2 later this week.

The Ruby gem for SugarCRM has already been briefly presented in a SugarCRM Developer Zone article, but has been drastically improved over the last months. In the following lines, we’ll go over a few of these improvements and show you how leveraging SugarCRM can be greatly improved.

Setting up

The gem is tested with Ruby 1.8.7 and 1.9.2, so you can pick your favorite version. Installing the gem is as easy as
gem install  sugarcrm
(note: depending on your particular setup, you might need to call ‘sudo gem install’ instead). If you don’t have a SugarCRM server setup to use for testing, try one of the SugarCRM stack installers. Since we’ll be executing simple, nearly-independent commands, feel free to follow along in an irb session.

Connecting

The first thing we need to do is
require 'sugarcrm'
after which we can connect to the actual SugarCRM server:
SugarCRM.connect('http://127.0.0.1/sugarcrm','admin','letmein')
(Naturally, this assumes you have your SugarCRM instance running.) You’ll notice that the URL points to where the SugarCRM server is available on the web server, not the actual index page, nor the API endpoint. If you’re following along in irb, you’ll see the gem dutifully returns a namespace similar to
SugarCRM::Namespace0
You can safely ignore this for now (we’ll tell you more about it in the advanced article).

Basic CRUD actions

On to our first subject: Create/Read/Update/Delete actions. Let’s start by seeing which contact was last entered in CRM:
puts SugarCRM::Contact.last.last_name
All SugarCRM modules (i.e. “Contacts”, “Opportunities”, etc.) are namespaced within the ‘SugarCRM’ Ruby module. So ‘SugarCRM::Contact’ gives us access to the ‘Contact’ Ruby class that will wrap all Contacts in CRM. (As a side note, any custom modules you may have created in Studio or loaded with the Module loader will be available in the same fashion.) From that class, we call the ‘last’ finder function (more on those below) which will return the record in SugarCRM with the latest ‘date_entered’ value. Finally, we call the ‘last_name’ attribute on the contact instance to get the person’s last name (which is then printed by Ruby). Let’s create a new contact:
c = SugarCRM::Contact.create(:first_name => 'John', :last_name => 'Doe')
With respect to creating new class instances and records in CRM, the gem behaves much like ActiveRecord: ‘new’ will create a new class instance without saving it to CRM, whereas ‘create’ will actually save  the class instance on CRM (i.e. create a new record). As we called ‘create’ in this case, our CRM should now have a new record. Let’s check:
puts SugarCRM::Contact.last.last_name # => Doe
Notice we’re calling the same methods as above: we’re still looking for the last created record. However, the output will be different, since we just created a new record. Let’s change John Doe’s last name:
c.last_name = 'Dot'
c.save!
To change the last name, we simply re-assign a value to the attribute. The attribute names always match the SugarCRM field names (which can be looked up in the Studio in the Admin interface), which means that any custom attributes (i.e. that have been added through the Studio tool) will end with ‘_c’. In other words, if we add a “middle name” field to our contact module using the Studio tool, we’ll access that field in the gem by calling ‘my_contact.middle_name_c’. Once again, the gem behaves like ActiveRecord: ‘save’ will attempt to save the record. If it’s unable to do so (e.g. some required fields are blank), it will simply return false. We’ll call ‘save!’ instead so that if the record can’t be saved, an exception will be raised and the code execution will stop. Now that we’ve gone through creating, reading, and updating, it’s time to bid farewell to John Doe:
c.delete

Associations

Let’s start by getting a SugarCRM account to work with. (We’ll learn more about finding specific module instances later.)
account = SugarCRM::Account.first
Let’s see how many contacts it has:
puts account.contacts.size
This account just hired a new receptionist. Let’s start by creating a contact in CRM for her (just like we did above):
alice = SugarCRM.create(:last_name => 'Angry', :first_name => 'Alice', :title => 'Receptionist')
Now we can add her to the account’s contacts:
account.contacts << alice
account.save!
You can also call ‘account.associate!(alice)’ which will link the two records and save the relationship in one step. There is a major implementation difference, though: when you call ‘account.contacts’, it loads all of the account’s contacts before creating the new association, which might take a long time. If you just want to make sure the two records are linked and haven’t already loaded the associated accounts, it’s usually best to call the ‘associate’ method. Let’s check Alice is now associated with the account, and see how many contacts this account now has:
puts account.contacts.include? alice
puts account.contacts.size
It turns out Alice wasn’t a great fit for the company (she didn’t really have people skills). Let’s remove her from that account:
account.disassociate!(alice)
You could, of course, simply call ‘alice.delete’ which would delete Alice’s record in CRM and all associated relationships, whereas what we did above simply remove the link between the two records, without deleting Alice’s record. (In other words, Alice is still in CRM.) Let’s print the full names of all contacts linked to this account, so we can make sure Alice isn’t among them:
account.contacts.each{|c|
puts "#{c.first_name} #{c.last_name}"
}
(Let’s quickly remove Alice from CRM: ‘alice.delete’)

Dynamic finders

Just like ActiveRecord, the gem provides dynamic finders with attribute names. Here’s an easy way to find the “Family Stationary” account:
SugarCRM::Account.find_by_name("Family Stationary")
As you’ll see below, this is simply a convenience method that calls a finder with a condition matching the attribute name (‘name’, in this case) and value (“Family Stationary”). Such methods are available for all attributes defined on your CRM modules. There is also an “all-in-one” method to ensure a record exists:
SugarCRM::Account.find_or_create_by_name("Family Stationary")
If the record exsits, it will be returned. If no such record exists, it will first be created in CRM, and then returned.

Finders

We’ve briefly seen how to use the default behavior of the ‘first’ and ‘last’ finders. As their name suggests, these finders will return, respectively, the first or last record matching the criteria (if no criteria is given, the default is to sort by date entered). But we can also give conditions to the query: let’s search for the first account in Los Angeles:
SugarCRM::Account.first(:conditions => {:billing_address_city => "Los Angeles"})
Notice that conditions are specified within a ‘:conditions’ array. By default, the query will search for records where the attribute is equal to the specified value (“Los Angeles” in this case). But there are other ways to use conditons, as you will see below. Let’s find the first account with a zip code between 50000 and 800000. Notice how, instead of a single value, we’ve used an array to specify several conditions (including operators). These conditions will be joined with an SQL ‘AND’ (if you want to use a query with complex boolean algebra, at the time of this writing you’ll need to use the direct API method the gem provides, as explained in the “advanced” article).
SugarCRM::Account.first(:conditions => {:billing_address_postalcode => ["> 50000", "<= 80000"]})
The last account in California that was created by the administrator (note how conditions are specified on multiple attributes):
SugarCRM::Account.last(:conditions => {:billing_address_state => "CA", :created_by_name => "Administrator"})
The gem also has (very limited) SQL operator support, although they must be all uppercase to be recognized. Let’s print all the accounts with “Inc” in their name:
SugarCRM::Account.all(:conditions => {:name => "LIKE '%Inc%'"}).each{|a| puts a.name }
Notice how this time, instead of calling ‘first’ or ‘last’, we called ‘all’. The finder syntax is the same for ‘all’, the difference lies in the return value: ‘first’ and ‘last’ will return either an instance matching the criteria or ‘nil’, whereas ‘all’ will return an array of matching object instances (or an empty array if there are none). This shows you how you can iterate across result sets as arrays. The better way to pass each record into a block is this way:
SugarCRM::Account.all(:conditions => {:name => "LIKE '%Inc%'"}){|a| puts a.name }
(Notice the absence of ‘each’.) The reason this way is superior is that when ‘each’ is used, we must must retrieve all matching records before iterating, which can be an issue if there are many. By passing the block directly to the finder as in the second example, records are yielded to the block as each record slice is retrieved. Finders also accept some SQL arguments: let’s print the list of the 10 last accounts (except the last one, due to the ‘offset’ value) sorted descending by name:
SugarCRM::Account.all(:order_by => "name DESC", :limit => 10, :offset => 1).each{|a| puts a.name }
Of course, you can also add a ‘:conditions’ hash in there. Also to be noted: as of this writing the SugarCRM REST API seems to have a bug where the limit and offset options don’t work correctly (the value for limit is always considered to be the smaller of the 2 values). This bug is fixed when using the gem: your query will return the expected results, even if the SugarCRM version you’re using has this bug. That’s how we roll… Want to learn more? Check out other articles on this gem: how to create a basic Rails portal for SugarCRM using this gem, and advanced gem use (covering thins like using configuration files for automatic login, extending the gem, etc.). Gem documentation can be found at https://github.com/chicks/sugarcrm, and questions/problems regarding the gem should be reported there also for quicker resolution.

{ 0 comments }

Announcing: Microsoft Dynamics CRM 2011 Implementation Guide update 5.1.0

May 19, 2011

Microsoft Dynamics CRM 2011 Implementation Guide update 5.1.0 is now available

Yes, it’s that time of year again where flowers are blooming, trees are burgeoning, and there’s a brand-spanking new update to the Microsoft Dynamics CRM 2011 Implementation Guide! Please note that this update will only be published to the TechNet and MSDN libraries.

Summary of changes

We strive to keep the information in this documentation as current and accurate as we can. The below table lists the changes that have been made as part of this documentation update.

Guide

Topic

Type

Explanation

Planning

Business Manager’s Role in a Microsoft Dynamics CRM Implementation

Revision

Moved the entire section out of the Planning Guide and moved it as a separate document that is not included with the Planning Tools download package.

Planning

Upgrading from Microsoft Dynamics CRM 4.0

Addition

Added a note that only the default organization is upgraded and additional organizations must be upgraded by using Deployment Manager.

Planning

SQL Server deployment considerations

Addition

Added bullet item about limited support when running Microsoft Dynamics CRM with a SQL Server that uses RCSI.

Planning

Active Directory and network requirements for Microsoft Dynamics CRM

Addition

Added a short sub-topic for IPv6 support.

Planning

Network ports for Microsoft Dynamics CRM

Addition

Added new subtopic for server role network port requirements.

       

Installing

Install Microsoft Dynamics CRM 2011 Server on a server without Microsoft Dynamics CRM installed

Revision

Revised Setup Wizard step on Specify E-mail Router Settings page to include that if you use a domain account for the Email Router service you must add that account to the PrivUserGroup.

Installing

Installing Microsoft Dynamics CRM for Outlook with Roaming User Profiles, Windows Server Remote Desktop Services, or Citrix Presentation Server

Addition

Added new topic for installing Microsoft Dynamics CRM for use with Citrix and Terminal Server.

Installing

Microsoft Dynamics CRM Reporting Extensions XML configuration file

Revision

Replaced "true/false" with "0/1" accepted values for autogroupmanagementoff element.

Installing

Sample Microsoft Dynamics CRM Reporting Extensions XML configuration file

Revision

Replaced "true/false" with "0/1" accepted values for autogroupmanagementoff and autoupdateconfigdb elements.

Cheers!

Matt Peart

Read the full article →

Statement of Direction for Microsoft Dynamics CRM 2011

May 12, 2011

I had it on my plate to review this document but the good folks at Sonoma beat me to it… again. So I pinged my good friend and CRM MVP Mike Snyder and got permission to repost it here for those of you who aren’t reading the Sonoma Partners blog regularly.

imageWe just got our hands on the updated Microsoft Dynamics CRM Statement of Direction from Microsoft, and we wanted to share our thoughts on the document. The Statement of Direction (SoD) outlines the future direction of Microsoft Dynamics CRM over the short and longer term. If you remember, Microsoft last updated this document back in April 2010…so this May 2011 SoD release is a pretty big milestone. While the May 2011 SoD is just 7 pages long (short compared to the 20 page April 2010 update), it does contain some goodies.

Here’s our highlights from the document:

  • Microsoft will remain committed to the “power of choice” allowing customers to deploy EITHER cloud-based and on-premise versions of Microsoft Dynamics CRM.
  • SOCIAL CRM! Yes of course social will be part of the future CRM roadmap. Some of the social and collaboration subpoints called out in the SoD include: micro-blogging, business activity feeds, and social intelligence.
  • Microsoft Dynamics CRM will continue to “harness and surface” the collaboration capabilities from Microsoft SharePoint, Microsoft Lync, and Microsoft Office. This is great to see the continued investment in making the Microsoft products work better together. While Microsoft’s Skype acquisition was too late breaking for this document, it wouldn’t surprise me to see some Skype-to-CRM integration in the future.
  • Improved provisioning and evaluation of Microsoft Dynamics Marketplace solutions, nice!
  • Improved reporting: additional charting, visualization and dashboarding capabilities. Who can argue with better, easier and sexier reporting?
  • Cross-device support: while the SoD does not provide details about specific devices CRM will support (iPad and iPhone?!?), it does call out different form factors such as desktop, PC, laptop, tablet and phone.
  • Multi-browser support: Microsoft Dynamics CRM will work on different web browsers by utilizing HTML5 (again no specifics about Chrome, Safari,etc.).
  • Better support for enterprise organizations to run Microsoft Dynamics CRM Online (as part of their IT infrastructure plus better on-boarding, admin and integration capabilities).

Of course this all sounds like GREAT new stuff and we can’t wait to get it! So we’re guessing the next question on your mind is when can customers expect to see new versions of Microsoft Dynamics CRM? The SoD covers future release timing too:

  • Instead of the traditional 3 years between major releases, Microsoft Dynamics CRM will change to a semi-annual release cycle (spring and fall).
  • Microsoft will release an “automatic update” to Microsoft Dynamics CRM Online in Q4 of calendar 2011. There will be a “scheduled update” to Microsoft Dynamics CRM Online in Q2 of calendar 2012.
  • As you would expect, automatic updates happen all at once while scheduled updates allow Microsoft Dynamics CRM Online customers to schedule their update within one year. I think it’s pretty safe to assume that scheduled updates will be larger in scope and complexity compared to automatic updates.
  • Microsoft will release an “update” for the on-premise version of Microsoft Dynamics CRM in Q4 of calendar 2011. An “upgrade” of the on-premise version of Microsoft Dynamics CRM will be available in Q2 of calendar 2012.
  • On-premise upgrades may incorporate significant Microsoft platform innovations (e.g. the next releases of Windows Server and desktop, .NET Framework, SQL Server, Office), while updates offer smaller scale new capabilities.

From a customer and partner perspective, I am really jazzed up about the semi-annual release cycles. It will be outstanding to get new features and capabilities more quickly. However from a book author perspective, I am slightly terrified! :)

Of course, you can download and read the Microsoft Dynamics CRM Statement of Direction from our website.

Enjoy,

Mike Snyder

Read the full article →

SugarCRM Chef Cookbook Published

May 11, 2011

After delaying cleanup on the code for a week or two, I’ve published my cookbook for deploying SugarCRM CE using Opscode Chef. The cookbook utilizes the community cookbooks from Opscode for deploying the standard LAMP stack on a machine, grabs a copy of the latest stable build of SugarCRM CE from Github, and creates a [...]

Read the full article →

Parameterizing Fetch Based Reports

March 18, 2011

As you may already know, we have introduced fetch based reports in Microsoft Dynamics CRM 2011. This means you can now upload powerful, custom fetch based reports even in Microsoft Dynamics CRM Online and CRM’s wizard reports are not the only available option. Other than fitting nicely into CRM Online scenarios, these reports are also a good candidate for On Premise deployments as they generally perform better when compared to an equivalent SQL report running against CRM’s Filtered Views.

You may read more about fetch based reports in the following blog posts:

Reports, as we all know, are typically used to present business data in a more meaningful way to the end users so that they can derive quick insights from it. In order to increase the value a report provides, it usually takes some additional inputs or parameters at runtime and uses them to adapt the content or presentation. One of the common usage patterns of these parameters is to use them within the data sets defined in the report and control the data being retrieved from the data source. Today, I am going to talk about how you can parameterize fetch statements used in a fetch based report. I will start with a description of how query parameterization works for fetch based reports followed by an explanation on the elements that support parameterization.

Fetch based reports allow certain parts of a fetch xml to be parameterized. In other words, fetch based reports can be designed to receive parameter values at runtime which can then be used by the fetch statements defined in the report. We allow value of certain fetch xml nodes or attributes to be parameterized, and at runtime the received value of the parameter is replaced in the fetch xml before it is executed to get the results. Let us take an example and see how this works.

Consider the following fetch xml that allows me to show sum of estimated revenue for opportunities in “3 – Negotiating” stage for each customer:

<fetch mapping='logical' count='10' aggregate='true'> <entity name='opportunity'> <attribute name='estimatedvalue' aggregate='sum' alias='sum_estimatedvalue'/> <attribute name='customerid' groupby='true' alias='customerid'/> <order alias='sum_estimatedvalue' descending="true" /> <filter type="and"> <condition attribute="stepname" operator="eq" value="3 - Negotiating" /> </filter> </entity> </fetch>

This will work nicely for me. But if I want to slightly enhance my report so that the user viewing the report can choose which stage the opportunities should be in, I need a way to change the value of the condition dynamically at runtime. This is exactly what parameterized fetch xml of fetch based reports is meant for. However, for the complete thing to work for a report, I need to do the following:

1. Define a report parameter, say stage, in the RDL which will be shown to the user at runtime and will receive an input from her for the stage she is interested in.

<ReportParameter Name="stage"> <DataType>String</DataType> <DefaultValue> <Values> <Value>3 - Negotiating</Value> </Values> </DefaultValue> <Prompt>Opportunity Stage</Prompt> </ReportParameter>

2. Define a query parameter, say @stepname, in the RDL for the data set and set its value to the report parameter using the expression =Parameters!stage.Value. The prefix “@” is important and I will talk about it in a moment.

<QueryParameter Name="@stepname">

      <Value>=Parameters!stage.Value</Value>

</QueryParameter>

3. Modify the condition node of the fetch xml to use the query parameter as follows:

<condition attribute="stepname" operator="eq" value="@stepname" />

I have replaced the value of the condition with the query parameter @stepname. As I said before, the “@” prefix is important. It acts as a hint for CRM that @stepname could be a query parameter that may receive a value at runtime. I say it’s a hint and not a certainty, because a condition can have a value that starts with “@” but is not a query parameter. E.g. a condition that email address that ends with “@microsoft.com” is a valid condition but is not expecting a query parameter. At runtime, CRM will parse the fetch xml for potential parameters and if there’s a matching query parameter available it will simply replace the parameter in fetch xml with the value of the query parameter.

And I am done. My parameterized report is ready to work! When I execute the report, I will be prompted to enter an Opportunity Stage according to which the data will be filtered.

clip_image002

Seemed like a lot of work, isn’t it? So, let’s make it a little easier for you. When you author a fetch based report using the BIDS extension that CRM provides, we do a bunch of work automatically for you. You only need to provide the fetch xml with the parameter hint, i.e. a value with a “@” prefix, and we will automatically create a report parameter and a query parameter for you to complete the parameterization support. You can change the parameter settings or prompt text as per your needs. In case you do not want the parameter at all, you are free to remove it later.

Now when you know how query parameterization works in fetch based reports, it is time to understand what all elements of a fetch xml statement can be parameterized. The elements that can be parameterized fall into the following three categories:

1. Paging Elements

These elements are meant to support paged data retrieval. Often times, a report spans a large number of records but it only show a subset or a page of the complete data set at a given point in time. If you want a report that can fetch and show data in paged manner, then these elements can be parameterized to support that.

<fetch mapping=’logical’ page=’@page’ count=’@count’ paging-cookie=’@cookie’ >

Using parameters for these elements, it is possible to build reports that fetch data only for the page that the user is presently viewing and can significantly improve a report’s performance. I am going to talk about this in more detail in my future posts.

2. Condition Elements

These elements are meant to supply operand values dynamically to a condition element of a fetch xml statement. This is useful if you want to apply a condition based on some values that you receive at runtime. There are the following two elements that can be parameterized under this category:

a. Value Attribute: <condition attribute="stepname" operator="eq" value="@stepname" />

We have already seen an example of such a parameterization. In addition to what was already explained, you can also make the query parameter receive an array of multiple values. Let’s take our example forward to understand this better. I had defined a report that allowed users to provide an opportunity stage at runtime. If I want my users to provide multiple opportunity stages instead of just one, I also need to do make the report parameter stage a multi valued report parameter in addition to the other steps mentioned before. This can be done by modifying the parameter properties to “Allow multiple values” as shown below:

clip_image004

This will cause report viewer control to allow the user running the report to enter multiple values for the stage parameter and at runtime CRM will use those multiple values to form an array of values for the fetch xml condition.

clip_image006

b. Value Node

<condition attribute="stepname" operator="in" >

     <value>3 – Negotiating</value>

     <value>@stage</value>

</condition>

In my report described earlier, let’s say I want all opportunities in opportunity stage “3 – Negotiating” to be considered always. Additionally, I want my users to provide one additional stage to filter the data. This can be done using the xml fragment shown above. One of the several values of the condition value array is parameterized.

3. Pre-filtering Element

This element is used to apply a pre-filter to an entity of the fetch xml statement at runtime. CRM supports a notion of report pre-filtering using which you can filter a report’s content at runtime using an advanced find query. This provides reports a flexibility that they can be defined only once but can be rendered against a differently filtered data set as and when needed. Taking our example report yet another step forward, if I want my report to have all the previously discussed functionality and in addition to that I want my users to be able to provide another filtering criterion so that the data set can be filtered on an adhoc basis. E.g. a user running the report should be able to run the report only for the opportunity owned by her. Using report pre-filtering, I can make the report to prompt the user with an Advanced Find control before executing the report. Then whatever filtering criteria is entered by the user, it is taken as the base filtering criteria for the report and any filtering defined by the report are applied on top of the filtered data set.

clip_image008

clip_image010

Pre-filtering parameters work slightly differently than the rest of the parameters and need not be prefixed with “@”. These parameters are defined using custom xml attributes that are not part of the standard fetch xml schema and are defined by fetch based reports for proprietary usage.

<entity name=’opportunity’ enableprefiltering=’true’ prefilterparametername=’opportunityfilter’>

Fetch based reports uses two xml attributes, namely enableprefiltering and prefilterparametername, under entity or link-entity nodes of a fetch xml for setting a query up for pre-filtering. As soon as the CRM extension for BIDS detect a fetch xml having these two nodes, it will automatically create corresponding report and query parameters. When you upload such a report to CRM server, CRM will also detect this usage pattern and will automatically modify the report. It will make the report parameter for pre-filtering as a hidden parameter and will prompt the users running the report with an Advanced Find user interface. It will then capture the filtering criteria entered by the user and will pass it to the report which will be used to pre-filter the report data set. The xml attribute prefilterparametername is an optional xml attribute and if not provided, CRM will generate a parameter with a default name “CRM_<entityname>” where entity name is the name given by the name attribute of the entity node.

I will be covering pre-filtering in more detail in my future posts but this information should be good enough for building pre-filterable fetch based reports.

You can use any of the above described ways of parameterizing your fetch based reports and gain more out of them. I hope that this post was useful for understanding the parameterization support that we have built. Keep your questions coming and wait for the next edition.

Cheers,

Abhishek Agarwal

Read the full article →

Fetch-Xml based Reports: Bits & Pieces

February 23, 2011

With Fetch-xml based reports in Microsoft Dynamics CRM 2011, users can now create custom reports in Microsoft CRM Online. The CRM Report Authoring extension for BIDS provides a rich authoring experience for creating such custom reports. Abhijit Gore has a great introduction post on authoring and updating fetch based report using BIDS. In this post, I will detail other features of fetch-xml based reports like Adding Parameters, Pre-filtering that will help you create better and effective reports.

1. Adding Parameters to a Fetch Based report:

Just like parameters in SQL queries, one can have parameters in Fetch-xml queries too. The advantage of having parameters is that their values can be set at runtime by the end user.
For example, you want to show all opportunities with Estimated Revenue greater than some value specified by the user. If you were creating the Report using BIDS with the CRM Fetch extension, you would write the following fetch-xml in the Query-Builder:

clip_image002

Parameter names need to start with “@” and their value is populated at runtime. The above query returns opportunities with EstimatedValue greater than the value of the parameter @MinEstimatedValue. Adding the parameter in the fetch query also adds the following QueryParameter and ReportParameter nodes in the RDL.

<QueryParameters>

  <QueryParameter Name="@MinEstimatedRevenue">

    <Value>=Parameters!MinEstimatedRevenue.Value</Value>

  </QueryParameter>

ryParameters>

 

rtParameters>

     <ReportParameter Name="MinEstimatedRevenue">

    <DataType>String</DataType>

    <Prompt>Min Estimated Revenue</Prompt>

  </ReportParameter>

ortParameters>

At runtime, the text from the “Prompt” node in the ReportParameter is displayed to the end user. The parameter value entered by the user is then used to populate the QueryParameter.

clip_image004

2. Pre-filtering in Fetch based reports:

One of the most useful features of Reports in CRM was to allow reports’ data to be filtered using Advanced Find functionality. Pre-filtering allows users to create context sensitive report – this post from Dana explains how pre-filters can be used for SQL based reports. But how do you add pre-filters to a fetch query? Well, it is fairly easy. All you need to do is specify an “enableprefiltering” attribute in the entity node of your fetch query. (The “prefilterparametername” attribute is optional):

 

<fetch>

      <entity name="opportunity" enableprefiltering="true" prefilterparametername="OpportunityFilter">

        <attribute name="name" />

        <attribute name="estimatedvalue" />

        <link-entity name="account" from="accountid" to="customerid" enableprefiltering="true" prefilterparametername="AccountFilter" >

        <attribute name="name" alias="accountname" />

        </link-entity>

      </entity>

</fetch>

As with parameters before, adding a pre-filter parameter in the fetch-query also requires adding a QueryParameter and ReportParameter node in the RDL.

<QueryParameters>

  <QueryParameter Name="OpportunityFilter">

    <Value>=Parameters!OpportunityFilter.Value</Value>

  </QueryParameter>

  <QueryParameter Name="AccountFilter">

    <Value>=Parameters!AccountFilter.Value</Value>

  </QueryParameter>

</QueryParameters>

 

<ReportParameters>

  <ReportParameter Name="OpportunityFilter">

    <DataType>String</DataType>

    <Prompt>Opportunity Filter</Prompt>

  </ReportParameter>

  <ReportParameter Name="AccountFilter">

    <DataType>String</DataType>

    <Prompt>Account Filter</Prompt>

  </ReportParameter>

rtParameters>

Once the report is uploaded into CRM and Run an Advanced Find dialog opens up. The pre-filter parameters are populated with fetch-xmls generated from this Advanced Find dialog.

(In BIDS, the pre-filter parameter will be visible as any another string value parameter. The expected input is a fetch-xml with filter conditions. Leaving the parameter value blank when prompted defaults it to a redundant filter – a fetch-xml that returns all attributes for all entity records).

image

3. Union Queries in Fetch based reports

The UNION operator in SQL allows you to combine two or more select statements and return the result as part of a single DataSet. The current fetch-xml schema does not have an operator that allows a similar UNION functionality. Instead, the workaround is to retrieve the results as part of different data sets.

Suppose you want names of all accounts and contacts in you organization. The SQL Query in your RDL would be:

<DataSet Name="DataSet1">

  <Query>

          <DataSourceName>SqlDataSource</DataSourceName>

          <CommandText> select fullname as name from FilteredContact UNION select name from FilteredAccount </CommandText>

        </Query>

</DataSet>

In a fetch based report, you would instead have two data sets one corresponding to each of the above select statements but using the same data source.

<DataSet Name="DataSet2">

 

    <Query>

      <DataSourceName>FetchDataSource</DataSourceName>

      <CommandText>&lt;fetch&gt; &lt;entity name="contact"&gt; &lt;attribute name="fullname" alias="name" /&gt; &lt;/entity&gt; &lt;/fetch&gt;</CommandText>

   </Query>

     </DataSet>

  <DataSet Name="DataSet3">

 

    <Query>

      <DataSourceName>FetchDataSource</DataSourceName>

      <CommandText>&lt;fetch&gt; &lt;entity name="account"&gt;  &lt;attribute name="name"/&gt; &lt;/entity&gt; &lt;/fetch&gt;</CommandText>

    </Query>

ataSet>

4. Multiple Datasets and Multivalued Parameter in Fetch based reports

Reports with multiple datasets would typically require utilizing results of one dataset in another dataset’s query. Let’s take the following example:

We want to generate a report that displays the top-15 accounts sorted by revenue and a 16th row that displays the total revenue for the rest of the accounts. We would again require two datasets – Dataset1 retrieves the top 15 records ordered by revenue while Dataset2 retrieves the TotalRevenue aggregating over all accounts except the ones from DataSet1.

<DataSet Name="DataSet1">

        <Query>

          <DataSourceName>FetchDataSource</DataSourceName>

          <CommandText>

&lt;fetch count="15"&gt;

              &lt;entity name="account" &gt;

                &lt;attribute name="accountid" /&gt;

                &lt;attribute name="name" /&gt;

                &lt;attribute name="revenue" /&gt;

                &lt;order attribute="revenue" descending="true" /&gt;

              &lt;/entity&gt;

        &lt;/fetch&gt;

    </CommandText>

  </Query>

</DataSet>

 

      <DataSet Name="DataSet2">

        <Query>

          <DataSourceName>FetchDataSource</DataSourceName>

          <CommandText>

&lt;fetch aggregate="true"&gt;

              &lt;entity name="account"&gt;

                &lt;attribute name="revenue" aggregate="sum" alias="TotalRevenue" /&gt;

                &lt;filter&gt;

                &lt;condition attribute="accountid" operator="not-in" value="@TopAccountIds"/&gt;

                &lt;/filter&gt;

              &lt;/entity&gt;

            &lt;/fetch&gt;

    </CommandText>

    <QueryParameters>

      <QueryParameter Name="@TopAccountIds">

        <Value>=Parameters!TopAccountIds.Value</Value>

      </QueryParameter>

    </QueryParameters>

  </Query>

</DataSet>

 

      <ReportParameter Name="TopAccountIds">

      <MultiValue>true</MultiValue>

      <Hidden>true</Hidden>

      <DefaultValue>

        <DataSetReference>

          <DataSetName>DataSet1</DataSetName>

          <ValueField>accountid</ValueField>

        </DataSetReference>

      </DefaultValue>

      </ReportParameter>

The Top 15 AccountIds retrieved from Dataset1 are taken in a multi-valued parameter called “TopAccountIds”. In the fetch-xml query in Dataset2, these parameter values are used as a filter to exclude accounts selected in Dataset1.

(Please note that the above multivalued parameter usage with fetch-xml will only work with the Microsoft Dynamics CRM 2011 RTM or later bits)

I hope that the above discussion helps you in authoring reports with parameters and pre-filters. In case you are experiencing issues with Microsoft Dynamics CRM 2011 Beta, please leverage the CRM Dev Forums.

Please let us know, via comments below, what topics you would like to see about CRM-Reporting in future blogs.

Cheers,

-Ankit Malpani

Read the full article →

Microsoft Dynamics AX Demo — Business Intelligence Features (Part 1 of 3)

February 22, 2011

This demonstration illustrates the value of reporting features provided by Microsoft Dynamics AX 2009 integrated with Microsoft SQL Server. To support users of different skill levels, Microsoft Dynamics AX 2009 provides reports that are located in customized employee role centers, plus out-of-the-box OLAP cubes, enabling users to extract data as needed.

Read the full article →

Microsoft Dynamics AX Demo — Business Intelligence Features (Part 1 of 3)

February 22, 2011

This demonstration illustrates the value of reporting features provided by Microsoft Dynamics AX 2009 integrated with Microsoft SQL Server. To support users of different skill levels, Microsoft Dynamics AX 2009 provides reports that are located in customized employee role centers, plus out-of-the-box OLAP cubes, enabling users to extract data as needed.

Read the full article →

Microsoft and Intel take Microsoft Dynamics CRM 2011 for a Test Drive

February 21, 2011

Here’s to the power of partnership.  Microsoft and Intel teamed up over the past month to test the performance of Microsoft Dynamics CRM 2011 to obtain a comparison with the figures obtained in a similar benchmark of Microsoft Dynamics CRM 4…

Read the full article →