Tuesday, August 17, 2010

Salesforce - Syncing a Quote in Apex

I've been working with Salesforce Quotes recently and overall I like the functionality. One thing that took me a little while to figure out, though, was how to sync a Quote with its Opportunity through Apex.

I spent a little bit of time looking through the Quote fields with Eclipse's 'Content Assist' feature, but the closest thing I was able to find was the IsSyncing field. I tried setting that to true but knew of the error message that was surely about to pop up, "Field is not writeable." Like other Salesforce Is*Action* fields, Quote.IsSyncing is read only and you cannot write to it through Apex directly. I then tried to find a built in method that duplicated the "Start Sync" button found on a Quote's layout page, though I found no such functionality.

So how do you go about syncing? The secret to syncing a Quote with its Opportunity lies not in the Quote's fields, but in the Opportunty's fields. A quick glance through those fields reveals a look-up relationship called SyncedQuote, and this field (actually SyncedQuoteId) is what allows us to sync a Quote. The implementation is easy, just a simple assignment:

// Begin syncing Quote with Opportunity. Same as pressing the "Start Sync" button on Quote layout
parentOpp.SyncedQuoteId = quoteToSync.Id;

If you want to stop syncing the Quote or start syncing a different Quote, you simply adjust the Opportunity.SyncedQuoteId field accordingly.

A limitation that I want to note is that the above code only works in an Apex Class, at least as of API Version 19. This means that you can sync a Quote through Apex in an standard Apex Class or an Apex Test Class, but not through an Apex Trigger. If you try to sync a Quote in an Apex Trigger you will receive an error message explaining this functionality.


  1. I got the same problem and I was just looking for such information. Thanks a lot.

  2. Hi,

    I want to add some information. I was also working with this functionality. If you call a Class which is modifying the SyncQuoteID, and call it via a Trigger, you will receive the same error message. However, if you call the Class explicitly (eg. From Dev Console) and pass an existing Opportunity record ID, it will go through.

    Also, if you want to clone an existing Opportunity with an associated Quote Record in which Syncing is on, and then try to clone the Opportunity using Clone() from Apex, it will not let u through if you do it via a Trigger. The solution to this problem is either create a VF Page and write the functionality in Controller of that VF page and call it via a Button. Or, if this doesn't have to be real-time, then the same functionality can be created using Batch Apex and by making it schedulable.


  3. Hi, I'm new programming apex and it would be really great if you could help me a little bit creating the function in the class to sync the opportunity-quote with a custom button.

    I have another question: do you know how its possible to overwrite the standard "view" layout of the quote. I can only overwrite the "edit" button with a visual force page but it doesn't work when I only want to "view" it.

    I hope you can help me,
    thanks Peter