web
You’re offline. This is a read only version of the page.
close
Skip to main content

Notifications

Announcements

No record found.

Community site session details

Community site session details

Session Id :

Close Related Won Quotes when Opportunity was Lost CRM 2011/2013 C#

Aileen Gusni Profile Picture Aileen Gusni 44,524

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

image

*After Close the Opportunity as Lost

image

*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

image

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:

image

Message: Lose
Primary Entity: opportunity
Event: Post-operation
Execution Mode: Synchronous

Result:

image

Hope this helps you!

Thanks.


This was originally posted here.

Comments

*This post is locked for comments