Close Related Won Quotes when Opportunity was Lost CRM 2011/2013 C#
When we close Opportunity is Lost, if you notice, it will not auto-close as lost all related Quotes.
It still remains the Won Quote there…
*Before Close the Opportunity![]()
*After Close the Opportunity as Lost![]()
*As you can see the Quotes are still having Won Status..Which our customer does want.
Sometimes we have requirement to Close All Quotes as Lost as well if the Opportunity was Lost in order to keep in sync each other.
*Remember you cannot close Opportunity if you still have Draft or Active Quotes![]()
So here is the code to Close All Quotes as Lost or Canceled when an Opportunity was Lost
#region variables
Guid guidOpportunityId;
List<Quote> quoteToBeCanceled = new List<Quote>();
#endregion
if (context.InputParameters.Contains("OpportunityClose") && context.InputParameters["OpportunityClose"] is Entity)
{
//create entity context
Entity entity = (Entity)context.InputParameters["OpportunityClose"];
if (entity.LogicalName != OpportunityClose.EntityLogicalName)
{
return;
}
try
{
//create target entity as early bound
OpportunityClose TargetEntity = entity.ToEntity<OpportunityClose>();
#region Close all Quotes if Opportunity was Lost
//get the Opportunity Id
guidOpportunityId = TargetEntity.OpportunityId.Id;
//get all quote related to this Opportunity
quoteToBeCanceled = GetQuoteToBeCanceled(baseContext, guidOpportunityId);
if (quoteToBeCanceled != null)
{
foreach (Quote quote in quoteToBeCanceled)
{
if (quote.StateCode.Value == QuoteState.Won || quote.StateCode.Value == QuoteState.Closed)
{
//have to be deactivated first as Draft
ConvertToDraftQuote(service, quote);
//have to be activated first before it closes the Quote
ActivateDraftQuote(service, quote);
}
if (quote.StateCode.Value == QuoteState.Draft)
{
//have to be activated first
ActivateDraftQuote(service, quote);
}
//finally Close the Quote (Active Quote will be directly closed
//You can Choose Canceled or Lost
//as Canceled
ExecuteCloseQuoteAsCanceled(service, quote, quote.QuoteNumber);
//as Lost
ExecuteCloseQuoteAsLost(service, quote, quote.QuoteNumber);
}
}
#endregion
}
catch (Exception ex)
{
throw new InvalidPluginExecutionException(ex.Message);
}
}
Query to Get All related Quotes from Opportunity
//return all of the Quote from related Opportunity to be Canceled/Lost
//I am using LINQ here..
public List<Quote> GetQuoteToBeCanceled(KonicaBaseContext baseContext, Guid guidOpportunityId)
{
//get the Quote to be canceled in same Opportunity, exclude the wonQuote
var quoteToBeCanceled = from x in baseContext.QuoteSet
orderby x.CreatedOn descending
where x.OpportunityId.Id == guidOpportunityId
select x;
if (quoteToBeCanceled.ToList().Count > 0)
{
return quoteToBeCanceled.ToList<Quote>();
}
else
{
return null;
}
}
And the Helper Code…
Which you can use this code (C# code) for other purposes, such as How to Activate a Draft Quote, and so on..
The helper code consists of:
1. Convert Quote back to Draft
2. Activate a Draft Quote
3. Close the Quote as Closed - Canceled
4. Close the Quote as Closed – Lost
Convert Quote back to Draft
//make the Quote as Draft first
public void ConvertToDraftQuote(IOrganizationService service, Quote erQuote)
{
// Activate the quote
SetStateRequest activateQuote = new SetStateRequest()
{
EntityMoniker = erQuote.ToEntityReference(),
State = new OptionSetValue((int)QuoteState.Draft),
Status = new OptionSetValue((int)1) //in progress
};
service.Execute(activateQuote);
}
Activate a Draft Quote
//activate the Draft Quote
public void ActivateDraftQuote(IOrganizationService service, Quote erQuote)
{
// Activate the quote
SetStateRequest activateQuote = new SetStateRequest()
{
EntityMoniker = erQuote.ToEntityReference(),
State = new OptionSetValue((int)QuoteState.Active),
Status = new OptionSetValue((int)2) //in progress
};
service.Execute(activateQuote);
}
Close the Quote as Closed - Canceled
//And finally Close the Quotes as Canceled
public void ExecuteCloseQuoteAsCanceled(IOrganizationService service, Quote erQuote, string strQuoteNumber)
{
CloseQuoteRequest closeQuoteRequest = new CloseQuoteRequest()
{
QuoteClose = new QuoteClose()
{
Subject = String.Format("Quote Closed (Canceled) - {0} - {1}", strQuoteNumber, DateTime.Now.ToString()),
QuoteId = erQuote.ToEntityReference()
},
Status = new OptionSetValue(6)
};
service.Execute(closeQuoteRequest);
}
Close the Quote as Closed - Lost
public void ExecuteCloseQuoteAsLost(IOrganizationService service, Quote erQuote, string strQuoteNumber)
{
CloseQuoteRequest closeQuoteRequest = new CloseQuoteRequest()
{
QuoteClose = new QuoteClose()
{
Subject = String.Format("Quote Closed (Opportunity Lost) - {0} - {1}", strQuoteNumber, DateTime.Now.ToString()),
QuoteId = erQuote.ToEntityReference()
},
Status = new OptionSetValue(5)
};
service.Execute(closeQuoteRequest);
}
Register the Plugin:![]()
Message: Lose
Primary Entity: opportunity
Event: Post-operation
Execution Mode: Synchronous
Result:![]()
Hope this helps you!
Thanks.
This was originally posted here.

Like
Report
*This post is locked for comments