RE: Need help to write custom workflow activity
Hi Mona,
Based on your description i think this would be doable via MS Flow - please see [View:https://flow.microsoft.com/en-us/connectors/shared_dynamicscrmonline/dynamics-365/:750:50. I am not referring to the old UI Workflow engine. However MS Flow is available only for CRM Online - not sure what you are using.
With regards to the code logic for the plug-in (you can use the same logic for either plugin or wf this could look something like below
public class DemoPlugin : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
// Obtain the execution context from the service provider.
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
// Get a reference to the Organization service.
IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = factory.CreateOrganizationService(context.UserId);
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
{
try
{
Entity entityA = context.InputParameters["Target"] as Entity;
//Get child EntityB
QueryExpression entityBQuery = new QueryExpression("EntityB");
//Get only child records
entityBQuery.Criteria.AddCondition("entityALookup", ConditionOperator.Equal, entityA.Id);
//Apply filter criteria
entityBQuery.Criteria.AddCondition("step", ConditionOperator.Equal, "abc");
entityBQuery.Criteria.AddCondition("status", ConditionOperator.Equal, "pqr");
//To get the last modified
entityBQuery.AddOrder("modifiedon", OrderType.Descending);
entityBQuery.TopCount = 1;
Entity entityB = service.RetrieveMultiple(entityBQuery).Entities.FirstOrDefault();
//proceed only if entity B exists
if (entityB != null)
{
QueryExpression activitiesQuery = new QueryExpression("activitypointer");
activitiesQuery.ColumnSet = new ColumnSet(true);
//Fetch only appointments
LinkEntity appointmentLink = activitiesQuery.AddLink("appointment", "activityid", "activityid");
appointmentLink.Columns = new ColumnSet(true);
//To get the last modified
activitiesQuery.AddOrder("modifiedon", OrderType.Descending);
activitiesQuery.TopCount = 1;
Entity appointment = service.RetrieveMultiple(activitiesQuery).Entities.FirstOrDefault();
//Only if child activity exists
if (appointment != null)
{
//Set sender and recipient (instantiate EntityReference accordingly)
Entity from = new Entity("activityparty");
from["partyid"] = new EntityReference();
Entity to = new Entity("activityparty");
to["partyid"] = new EntityReference();
Entity email = new Entity("email");
//copy here attributes from appointment entity
// set actitivy party
email["from"] = new Entity[] { from };
email["to"] = new Entity[] { to };
//create
Guid emailId = service.Create(email);
//send the email
SendEmailRequest sendEmailreq = new SendEmailRequest
{
EmailId = emailId,
IssueSend = true
};
service.Execute(sendEmailreq);
}
}
}
catch (Exception ex)
{
throw new InvalidPluginExecutionException($"Error during plugin execution: {ex.Message}");
}
}
}
}
This however needs to be adapted to the entities that are being used in your CRM Organization.
Please keep in mind that the code as is above is only an example and needs refactoring before being shipped into production (handle cases where child records don't exist, extract methods, etc.) It's written purely as an example to be able to view the flow.
However if you are uncomfortable with writing code, then i suggest reaching out to an MS Partner for assistance.
Hope this helps you,
Radu