Wednesday, September 23, 2009

How to design a Custom Activities/History tab to show Activity Party information

There have often been requests for displaying the Activity Parties in the Activities/History tab of Account/Contact.

The details in these views are gathered from the ActivityPointer entity. The activity pointer entity is not customizable and so you are stuck with not having the activity party information like Sender/Receiver not being available for reference in the views.

However it is not that difficult to get a custom page to develop that does just this.

Let’s look at the various aspects related to this.

1. The Activities/History tab display not only activities directly associated with the account but also related entities of account.

How do we get this? The answer lies in the “TargetRollupActivityPointer” messages available in the SDK.

There are three different variation of this message available

· TargetRollupActivityPointerByAccount
· TargetRollupActivityPointerByContact
· TargetRollupActivityPointerByOpportunity

Searching the SDK for these messages should help you get you going with these messages.

// Create the target for the request.
TargetRollupActivityPointerByAccount target = new TargetRollupActivityPointerByAccount();
target.AccountId = new Guid("A0F87168-4B00-4CA2-925D-AA0A4C47B86F");

2. Get the Activity Parties Associated with these activities.

The information regarding the parties involved in an activity is not stored along with the activity but rather in a separate entity called activityparty.

You can query for activity party and search for activityid = activitypointer.activityid.

Note the result will return more than one records. This entity stores not just the sender/receiver but also the owner and organizer and such other activity party information. The participation type mask attribute describes the role of this party in the activity (search for activitypartytype in SDK for the entire list).

// Create the ConditionExpression.
ConditionExpression condition = new ConditionExpression();

// Set the ConditionExpressions Properties so that the condition is true
condition.AttributeName = "activityid";
condition.Operator = ConditionOperator.Equal
condition.Values = new string [] {activityid.ToString()};

// Set the properties of the QueryExpression
query.EntityName = EntityName.activityparty.ToString
query.ColumnSet = new AllColumns();

3. If you want to go further and be ambitious enough to add a column for displaying an attachment flag in case of emails with attachment.

CRM store the Email attachment information in the "activitymimeattachment" entity. You can filter this entity and look for activityid = activitypointer.activityid. If it returns any row it has attachments associated with it and you can add “true” flag for this.


// Create the ConditionExpression
ConditionExpression condition = new ConditionExpression

// Set the ConditionExpressions Properties so that the condition is true
condition.AttributeName = "activityid
condition.Operator = ConditionOperator.Equal
condition.Values = new string [] {emailId.ToString()};

// Set the properties of the QueryExpression
query .EntityName = EntityName. activitymimeattachment.ToString(); query.ColumnSet = new AllColumns();


Following the 3 – steps explained above you can get your custom page working the way you want.

Monday, September 14, 2009

Add Shortcut button for new Activity on CRM toolbar

Some time back we had posted a script that would allow you to create an ISV button to bring up the new activity form (phone call, appointment etc).

Recently we had the same request from one of our customers and we were quick to offer them the same. Unfortunately it failed. The locAddActTo function is not available on main CRM form.

To get this done, we had to provide the following alternate script


<Button Icon="/_imgs/ico_16_4210_d.gif" JavaScript="window.open('/activities/phone/edit.aspx','null','height=500px,width=800px,resizable=1,status=yes,toolbar=no,menubar=no,location=no')"> <Titles> <Title LCID="1033" Text="New Phonecall" /> </Titles> <ToolTips> <ToolTip LCID="1033" Text="Create New Phonecall" /> </ToolTips>

</Button>

Tuesday, September 1, 2009

Sales Quotas for Sales Person in Dynamics CRM

One of the not so widely discussed features of Dynamics CRM is the Sales Quota. You are bound to have missed this feature unless you have completed the Fiscal Year settings of the CRM organization.

To set the fiscal settings of the system, Go to settings Business Management and click on the Fiscal Year Settings.

Suppose you have set the following setting shown in the below screenshot.

Once the fiscal settings have been defined, the Sales Quota option is available on the System User record for settings the Sales quota of a Salesperson based on the first period settings.

You can set the Quotas for different fiscal periods as shown in the below screenshot. The fiscal period displayed in the below screen depends on the fiscal period settings in the above screen.


The Current Fiscal year tab will display the Current Year quota defined for the particular Salesperson.

Though CRM provides a way to define the Sales quota for a Salesperson, it ends at that and there is a lot left to be done in this area. They have not provided for any Actual/Quota comparison that would be considered essential once the Quota has been defined. There is a lot of scope for developing this functionality further through add-ons.

Friday, August 28, 2009

How to convert a RetrieveMultiple query written Server side to SOAP message to be used in Javascripts

It has often been seen that a RetrieveMultiple query that is very easy to write using the server side Query Expression objects using CRM webservices becomes difficult to achieve if we need to create a SOAP message for the same.

In this article we hope to explain each of the elements involved in the writing of SOAP messages to be used through Javascripts.

Let us take a simple RetrieveMultiple code as an example.

While writing the SOAP message the first component required is the SOAP envelope. This is the same at all times for all SOAP messages.

"<?xml version='1.0' encoding='utf-8'?>"+
"<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'"+
" xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'"+
" xmlns:xsd='http://www.w3.org/2001/XMLSchema'>"+

Next we need to add the Authentication Header that needs to be passed along with the SOAP message for successful authentication with the CRM Web service. CRM has an inbuilt function GenerateAuthenticationHeader() that can be used for this purpose.

var authenticationHeader = GenerateAuthenticationHeader();

SOAP Body is where the actual SDK message to be executed is included.

"<soap:Body>"+

In our example we are using the RetrieveMultiple Message so we provide the Message name and the schema reference to the CRM webservices

"<RetrieveMultiple xmlns='http://schemas.microsoft.com/crm/2007/WebServices'>"+

The parameter to a Retrieve Multiple Message is always a query expression

QueryExpression query = new QueryExpression();

"<query xmlns:q1='http://schemas.microsoft.com/crm/2006/Query'"+
" xsi:type='q1:QueryExpression'>"+


Now include all properties of the Query object that you set.

Entity name

query.EntityName = EntityName.incident.ToString();

"<q1:EntityName>incident</q1:EntityName>"+

Column Set

query.ColumnSet = new AllColumns();

"<q1:ColumnSet xsi:type='q1:ColumnSet'>"+
"<q1:Attributes>"+
"<q1:Attribute>title</q1:Attribute>"+
"<q1:Attribute>incidentid</q1:Attribute>"+
"</q1:Attributes>"+
"</q1:ColumnSet>"+

Criteria

ConditionExpression condition = new ConditionExpression();
condition.AttributeName = "title";
condition.Operator = ConditionOperator.Like;
condition.Values = new string [] {strSearchText};

"<q1:Criteria>"+
"<q1:FilterOperator>And</q1:FilterOperator>"+
"<q1:Conditions>"+
"<q1:Condition>"+
"<q1:AttributeName>title</q1:AttributeName>"+
"<q1:Operator>Like</q1:Operator>"+
"<q1:Values>"+
"<q1:Value xsi:type='xsd:string'>"+searchtext +"</q1:Value>"+
"</q1:Values>"+
"</q1:Condition>"+
"</q1:Conditions>"+
"</q1:Criteria>"+

Here, we have used 'Like' condition operator, likewise one can use any of the sdk supported operators and change the values to be matched accordingly.


Order by

OrderExpression oe = new OrderExpression();
oe.AttributeName = "title";
oe.OrderType = OrderType.Ascending;
query.Orders = new OrderExpression[]{oe};

"<q1:Orders>" +
"<q1:Order>" +
"<q1:AttributeName>title</q1:AttributeName>" +
"<q1:OrderType>Ascending</q1:OrderType>" +
"</q1:Order>" +
"</q1:Orders>" +

Once you have set all of these… your SOAP message is ready for execution.

Wednesday, August 26, 2009

How to Bulk Edit Attributes that show up Disabled on the Bulk Edit Form

We came across this really tricky situation and we would like to thank Microsoft for having a KB article (http://support.microsoft.com/kb/949941) for this.

We wanted to bulk edit a few of the accounts using the Actions => Edit option. The form that comes up here displays all attributes available for the Account entity. You would however notice that some of them are disabled though. Since we had 2 custom picklist type of attributes, one showing up as enabled the other disabled, it was easy to identify the possible reasons for disabling this one had custom code written on its onchange event while the other did not.

But we still wanted to be able to Bulk Edit this attribute without having the need to create a custom page just for editing a custom picklist attribute. Our search lead to the following KB article that explains the steps to enable this.

To have this explained in short, the entity customization file has a property “BehaviourInBulkEditForm” for the event tags. This determines the behavior of the attribute and the code written on the event. The valid values are

Enabled -- If you use this value, the field is enabled. Additionally, the code for the event is run when the event is called.
Disabled -- If you use this value, the field is disabled.
EnabledButNoRender -- If you use this value, the field is enabled. However, the code for the event is not run when the event is called.

Exporting the customization and making the below change should enable the attribute and not have the code written on the onchange event fired

<event name="setadditionalparams" application="true" active="true" behaviorinbulkeditform="EnabledButNoRender">