Audit of entity state change does not work when 'Closing'

May 19, 2010 at 10:15 PM

We have implemented this solution and for the most part it seems to be working great. However there is a problem when changing the state of an 'Opportunity' from Open to Closed. The change triggers the Update of opportunity step but not the SetStateDynamicEntity of opportunity step. We end up with 2 audit records, one with only modifieddate in the auditdetails set and one with zero auditdetails records. However, when the state is going from Closed to Open the auditing works fine. We do have another plugin that gets fired on the Update of opportunity step which, in certain circumstances, can update the state and re-save the opportunity. We have tried various combinations of step ordering and running synchronous vs asynchronous. Ideas?

May 26, 2010 at 6:11 PM

So for anyone interested here is how we ended up handling this. Auditing for closing an opportunity is handled separately from this audit plugin. When an opportunity gets closed either a Lose or Win message gets fired. So we register a new plugin, OpportunityWinLosePostUpdate, against these two events. The values that change when an opportunity gets closed are statecode, statuscode, actualvalue, actualclosedate and description. When an opportunity is open, all of these values except for state and status are null. If you get the oportunityclose entity from the context input parameters it contains all the new values. So, actualvalue, actualclosedate and description are all null to start and the updated values are in the opportunityclose entity. The new statecode (Win or Lose) is also in the opportunityclose entity. Statecode always starts as Open, since we were closing an open opportunity. So, the only before value that we could not capture from the Win or Lose context was the statuscode. We added a custom string attribute to the opportunity entity called preClosedStatus. We created a separate plugin, OpportunityWinLosePreUpdate, that also runs on Win or Lose but it runs synchronously on the Pre Stage pipeline. All it does is store the current statuscode of the opportunity in our new custom field so we have it during the Post Stage pipeline. Then, in the post stage asynchronous plugin, we can retrieve the updated opportunity by the opportunityid strored in the opportunityclose entity. We grab the value stored in preClosedStatus and create our audit records.

To get the opportunityclosed entity from the context and the opportunityID from that:

DynamicEntity closeRequest = (DynamicEntity)context.InputParameters["opportunityclose"];
Guid oppID = ((Lookup)closeRequest.Properties["opportunityid"]).Value;


Nov 2, 2010 at 4:54 PM
Edited Nov 2, 2010 at 5:02 PM

Apparently, when closing an opportunity an input parameter called 'Status' is returned, it is nothing but the 'statuscode' and is of type Int32 (the picklist value).

It will always be the current selected 'status reason', and is returned on message 'Lose' on the 'opportunity' entity on both pre/post pipeline stages.

string test = context.InputParameters["Status"].ToString();

Hope this helps someone!