Jun 27, 2013

Plugin for opportunity Win / Lose

It can be a common requirement to execute plug-ins when opportunities are closed as Win or Lose. In most cases you need to identify two cases separately. Ironically, I didn’t find many resourceful articles about it. In fact, I thought of sharing my experience.

These are the relevant statecode and statuscode combination for opportunity.


First one could think of having a State Change plug-in for this. But I learned it’s not successful.

Whether it is Win or Lose, opportunity will be closed. So it creates a record in OpportunityClose entity. Then I though, we could do a create plug-in for OpportunityClose entity. Now the problem is you are not able to catch whether it’s a Win or Lose. If your requirement is just to do something when opportunity is closed, this works.

Then only I decided to do two different plugin for Win message and Lose message which triggers the plugin in the correct action.

So correct plugin registration steps would be seen as below;



Then I checked the plug-in context which made me shocked again. It doesn’t have opportunity record but it does have an OpportunityClose.


OpportunityClose is of course an unfamiliar entity for me. For you too obviously! Then only I realised it should be called a “Black Sheep”. You know why? Could you guess the primary Key of this entity? Your obvious answer should be opportunitycloseid which is completely wrong! Check below picture. It is Activityid!

Anyway, strangeness of primary key was explained only for your knowledge. The good side is this entity contains opportunityid which is the gateway for all the attributes of our current record. So for both Win and Lose plugins I started coding as below, by passing the OpportunityClose instead of Opportunity, knowing that it contains opportunityid.

context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
service = factory.CreateOrganizationService(context.UserId);

if (context.InputParameters.Contains("OpportunityClose"))
{
   oppCloseEnt = (Entity)context.InputParameters["OpportunityClose"];
   .........
   .........
}

In summery I am passing opportunityclose, read opportunityid in it, retrieve opportunity fields I need using the service. In a way, it’s like asking something about your home from your neighbour! Anyway, it worked for me!

1 comment:

  1. Much clear code;

    Guid opportunityId = Guid.Empty;
    if (Context.InputParameters.Contains("OpportunityClose") && Context.InputParameters["OpportunityClose"] is Entity)
    {
    Entity entity = (Entity)Context.InputParameters["OpportunityClose"];
    if (entity.Attributes.Contains("opportunityid") && entity.Attributes["opportunityid"] != null)
    {
    EntityReference entityRef = (EntityReference)entity.Attributes["opportunityid"];
    if (entityRef.LogicalName == "opportunity")
    {
    Guid OppID = entityRef.Id
    }
    }
    }

    ReplyDelete