Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use ActivityPointer entity to set same state on different activity types? CRM 2011

I need to make sure the state of all activities related to a case (incident) entity in CRM 2011 are set to completed before I can set the state of the case itself to resolved.

I can do several retrieves to get all the possible activity types independently and then do an appropriate SetStateRequest(...) on each type. This article seems to suggest that an ActivityPointer record is created every time any activity type record is created and that both records have the same ID. Sure enough, when I look at cases and activities, every activity type record has an associated ActivityPointer record with the same ID. So far so good.

Does this mean that I can do a single retrieve of all ActivityPointer records that relate to my case and set the state on them to achieve a cross-type activity state setting? I suppose I'm not understanding what the purpose of ActivityPointer is if it doesn't allow me to do generic activity manipulations. Is that the point if it? Also, the ActivityPointer entity doesn't have a SetStateRequest message so can someone explain how I go about setting statecode/status on an ActivityPointer record? Ideally I want a state of completed and a status of cancelled.

Update: This blog seems to show exactly what I want although the offical docs on SetStateRequest seem to indicate that it doesn't support the ActivityPointer entity. I'll try this tomorrow but if anyone has advice on the best way to proceed I'd be obliged.

Update2: On further reading, I think the situation is that an ActivityPointer entity can only have it's state set. So I should be able to set all the activitypointer records to a state of cancelled per this setup. I suppose it makes sense that I cannot generically set the "Status Reason" as it differs between activity types. I'm still a bit confused about the previous link in that it seems to suggest that I can set the State and the Status of an activitypointer but it's not clear if this is true, what values combos are allowed and what they mean...

like image 565
keerz Avatar asked Dec 27 '22 09:12

keerz


2 Answers

The best way I can explain Activity Pointer is that it is the base class to derived classes like Email and Phone Call.

Activity Pointer encapsulates the base attributes of any activity so if you create a custom activity it too will extend from Activity Pointer.

From this it makes sense that Activity Pointer contains the State and Status values of all activities but also makes sense that it cannot be accessed from the SetStateRequest.

I imagine the actual State of the activity, Open, Closed, Scheduled, Cancelled, is applicable to all activities, but the Status is individual to each activity.

Eg. a task can be open but its status reason could also be open Whereas an email can also be open but its status reason is "Waiting to be Sent"

Due to this differentiation the SetStateRequest probably won't let you run it on ActivityPointer but it would on each individual activity entity.

In terms of doing what you have set out to do, the supported way would be to retrieve all the associated activites individually and then perform a set state request.

You can do it all at once like you want to but would involve a bit of "un-supportedness" in that you would probably have to do it on the database directly. However when setting the state to Complete the status reason would also have to reflect a status that belongs to that state. Otherwise I believe the activities would error.

So unfortunately I can't see a way around it in an elegant way but please do update if you find one!

like image 111
Chris Avatar answered Dec 29 '22 23:12

Chris


Chris. I'm answering my own question here because there is a way to use the activity pointer record to generically close all activity types. It may be one of the reasons why there is such a record. It relies on the fact that an activity pointer record has a field that defines what kind of activity it represents. Here's the code:

// do a search for all activities that have a status of open or scheduled
// that covers them all
// here's the filter expression to use
/*
FilterExpression filterStateCode = new FilterExpression();
            filterStateCode.FilterOperator = LogicalOperator.Or;
            filterStateCode.AddCondition("statecode", ConditionOperator.Equal, "Open");
            filterStateCode.AddCondition("statecode", ConditionOperator.Equal, "Scheduled");
*/
// the search returns a list of entities called AllOpenRelatedActivities

foreach (var currentActivityPointer in AllOpenRelatedActivities.Entities)
            {
                if (currentActivityPointer.Attributes.Contains("activityid") & currentActivityPointer.Attributes.Contains("activitytypecode"))
                {
                    currentActivityPointer.LogicalName = currentActivityPointer.Attributes["activitytypecode"].ToString();
                    currentActivityPointer.Id = (Guid)currentActivityPointer.Attributes["activityid"];

                    SetStateRequest setState = new SetStateRequest();
                    setState.EntityMoniker = currentActivityPointer.ToEntityReference();
                    setState.State = new OptionSetValue();
                    setState.State.Value = 2;
                    setState.Status = new OptionSetValue();
                    setState.Status.Value = -1;



                    SetStateResponse setStateResponse = (SetStateResponse)service.Execute(setState);


                }
            }
like image 45
keerz Avatar answered Dec 29 '22 23:12

keerz