Monday, June 1, 2009

Deactivate accounts with no activity for the last two years

Sometimes you need to write maintenance operations that operates on the entire database, not just a single record. MS CRM does not support such operations out-of-the-box, but it's quite easy to accomplish anyway.

Some MS CRM customers operate with very large datasets with lots and lots of accounts. Most of those accounts will be inactive, meaning that there's been no activity with them for a given amount of time.

In those cases the client might want to differentiate between those accounts who have an active relation with the client, and those who hasn't. This makes it easy to maintain the overview over the clients actual accounts, and also conduct datamining and filtering on the others in order to do antichurn campaigns, prospecting, etc.

To achieve this it might be feasible with some sort of mechanism that deactivates an account if there has been no activity for a given amount of time. In my other posting I explained how to set up a recurring workflow for maintenance, and this custom workflow activity could easily be integrated in such an workflow.

The workflow is quite simple. It's basically just a query that retrieves all customer accounts where the related activities haven't been modified for the last 24 months. This is just a sample criteria, you could just as easily used the modifiedon-attribute on the account entity or some other sort of criteria.

After all the accounts that meet this criteria are retrieved, the businessentitycollection that contains those accounts are enumerated and the statecode is set to inactive. Each account is then updated:

[CrmWorkflowActivity("Account maintenance")]
public class AccountMaintenanceWorkflow: Activity
{
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
IContextService contextService = (IContextService)executionContext.GetService(typeof(IContextService));
IWorkflowContext context = contextService.Context;

ICrmService crmService = context.CreateCrmService();

QueryExpression query = new QueryExpression();

query.EntityName = "account";

ColumnSet columns = new ColumnSet();
columns.Attributes.Add("statecode");
query.ColumnSet = columns;


LinkEntity linkEntity1 = new LinkEntity();
linkEntity1.JoinOperator = JoinOperator.Natural;
linkEntity1.LinkFromEntityName = "account";
linkEntity1.LinkFromAttributeName = "accountid";
linkEntity1.LinkToEntityName = "activitypointer";
linkEntity1.LinkToAttributeName = "regardingobjectid";

linkEntity1.LinkCriteria = new FilterExpression();
linkEntity1.LinkCriteria.FilterOperator = LogicalOperator.And;

ConditionExpression condition1 = new ConditionExpression();
condition1.AttributeName = "modifiedon";
condition1.Operator = ConditionOperator.OnOrBefore;
condition1.Values = new object[] { System.DateTime.Today.AddYears(-2).ToString() };

linkEntity1.LinkCriteria.Conditions.Add(condition1);

query.LinkEntities.Add(linkEntity1);


query.LinkEntities.Add(linkEntity1);
AccountStateInfo accStateInfo = new AccountStateInfo();
accStateInfo.Value = AccountState.Inactive;
foreach (account acc in crmService.RetrieveMultiple(query).BusinessEntities)
{
acc.statecode = accStateInfo;
crmService.Update(acc);
}


return ActivityExecutionStatus.Closed;

}
}


Just create the usual class library, reference all the usual stuff, and paste in the class. When you're done, compile and register with pluginregistration.exe.

When you've registered, you can incorporate this custom workflow activity with the recurring workflow example.

By the way, this activity will typically take some time to complete since it involves potentially a lot of updates. Make sure it only runs at night!

1 comment:

  1. Hi,
    To get a good job, just focus your Search job, make it so that you can find the jobs that aren't readily available.

    ReplyDelete