My colleagues need to create a number of quotations on an opportunity, send them out and then when the customer comes back with their decided quote, the quote needs to be synced to the opportunity line items to make the opportunity value correct. I've created a process that allows a number of quotations to be created and sent out at once.

I've written a trigger to copy the opportunity line items from the opportunity into the Quote line items, including 3 custom fields I have created called Start_Date__C, Duration__c and End_Date__c.

That trigger works but now I need all the information from the chosen quotation to be taken from the Quote Line Items back into the Opportunity Line Items, including the custom fields as there is often a lot of changes to add. I've written a trigger which is below, but nothing is happening when I try to sync my chosen quote. Is there something I'm missing?

trigger QuotetoOppSync on OpportunityLineItem (after insert) {

    //Query opportunity line items
    List<OpportunityLineItem> olis = [SELECT Id, PricebookEntry.Product2Id, OpportunityId, 
        Start_date__c, Duration__c, End_date__c FROM OpportunityLineItem 
        WHERE Id IN: Trigger.new];
    //Get a list of all opp ids:
    List<id> oppids = new List<id>();
    for (opportunityLineItem oli:olis){

    //Query QuoteLineItems by Opportunity ID
    Map<Id, QuotelineItem> producttoQli = new Map<Id, QuoteLineItem>();
    List<QuoteLineItem> qlis = [SELECT Id, PricebookEntry.Product2Id, Start_date__c, Duration__c,
        End_date__c, Quote.OpportunityId FROM QuoteLineItem 
        WHERE Quote.OpportunityId IN :oppIds];

        for(QuoteLineItem qli:qlis){
            productToQli.put(qli.PricebookEntry.Product2Id, qli);

    //Iterate across quote line items
    for (OpportunityLineItem oli : Olis){ 
        Quotelineitem qli=productToQli.get(oli.PricebookEntry.product2Id);
        if(qli != null){
            if(qli.Start_Date__c != null){ oli.Start_Date__c=qli.Start_Date__c;}
            If(qli.Duration__c != null) {oli.Duration__c=qli.Duration__c;}
            if(qli.End_Date__c != null){ oli.End_Date__c=qli.End_Date__c;}

    update olis;
  • 2
    Without looking at your code too in depth, your trigger is only firing on insert. Aren't you talking about updated line items and wouldn't your trigger need to also fire on update?
    – greenstork
    Commented Jun 30, 2014 at 17:27
  • Hmm, adding the update instead of insert I got this error... Commented Jul 1, 2014 at 9:46
  • Apex trigger QuotetoOppSync caused an unexpected exception, contact your administrator: QuotetoOppSync: execution of AfterUpdate caused by: System.DmlException: Update failed. First exception on row 0 with id 00kL0000004HIpJIAW; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, QuotetoOppSync: maximum trigger depth exceeded OpportunityLineItem trigger event AfterUpdate for [00kL0000004HIpJ, 00kL0000004HIpL] Commented Jul 1, 2014 at 9:46

1 Answer 1


Sycning Quotes and Opportunities is a pretty common requirement. There is a force.com labs package, Custom Quote Sync that will do what you want without writing a trigger.

The source code is public if you want to look at how they implemented it.

  • Thanks Ralph, but I have tried that application in the past but it does not take over Date data fields because of the "/" used in the field. Hence my need for a trigger to sort this out, unless you have heard of an alternative application? Commented Jul 1, 2014 at 9:05
  • @EmmaMillar if you're running into issues with that package I'd suggest install the unmanaged version from github and then addressing the bug you're encountering, would be a lot quicker than starting from scratch. Commented Jul 1, 2014 at 20:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .