I have a custom workflow activity that executes on delete of a entity that is a child in a parent-child relationship.
When the parent entity is deleted there is a database error.
I have tried checking that the parent entity is not null before running the workflow, but it is not null when the children are deleted; CRM must delete the children first.
I have implemented my own Opportunity Product entity (called Opportunity Line).
When an Opportunity Line is created, changed, or deleted a synchronous custom workflow activity executes.
The workflow creates a hidden write in Opportunity Product (the original entity) with a revenue equal to all the Opportunity Lines added together; this is done so that the system will calculate the est. revenue. I tried updating the est. revenue field directly, but was having problems when the Opportunity was set to system calculated.
/* Deletes all Opportunity Products for this Opportunity and adds a single write in product
* with the amount equal to the sum of all Opportunity lines
* If the current message is delete then do not include the current record in the calculation
* */
private void UpdateOpportunity(WorkflowContext context) // WorkflowContext contains everything retrieved from the CodeActivityContext
{
if (context.TargetReference != null || context.Target.Contains("wl_revenue")) // this is a delete or revenue update (or new record)
{
var linq = context.Linq;
var service = context.Service;
var lineId = (context.Target != null) ? context.Target.Id : context.TargetReference.Id; // context contains Target and TargetReference, Target is an entity and TargetReference is an Entity Reference, one is always not null
var opp = linq.wl_opportunitylineSet
.Where(line => line.Id == lineId)
.Select(line => line.wl_Opportunity)
.FirstOrDefault();
if (opp != null)
{
var oppId = opp.Id;
if (oppId != null)
{
var lineAmounts = from line in linq.wl_opportunitylineSet
where line.wl_Opportunity.Equals(oppId)
where line.Id != lineId // The current line cannot be retrieved as it is the record in the transaction
select line.wl_Revenue;
decimal revenue = (context.Target != null && context.Target.Contains("wl_revenue"))
? context.Target.GetAttributeValue<Money>("wl_revenue").Value : 0; // add the amount for this line if it just changed or was created
foreach (var amount in lineAmounts)
revenue += (amount != null) ? amount.Value : 0;
var oppProducts = from line in linq.OpportunityProductSet
where line.OpportunityId.Equals(oppId)
select line.Id;
foreach (var line in oppProducts) // there should be 0 or 1
service.Delete(OpportunityProduct.EntityLogicalName, line);
service.Create(new OpportunityProduct
{
IsPriceOverridden = true,
IsProductOverridden = true,
ProductDescription = "Income",
OpportunityId = opp,
PricePerUnit = new Money(revenue),
Quantity = 1
});
}
}
}
}
This works in all situations except when the parent Opportunity itself is deleted. Should this be done another way or is it possible for the workflow not to execute if it is the Opportunity being deleted, as a pose to an individual line?
I have to have a custom Opportunity Line, mostly because Opportunity Product cannot be used in any custom 1:N relationships.