function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Steve HarrisonSteve Harrison 

Need apex trigger code for updating Opportunity stage when quote is emailed

Hello,

I want the Opportunity stage to update to the "Proposal/Price Quote Sent" picklist value when a quote is emailed. I was not successful at creating a workflow rule and field update and the user forum indicated this is only possible through an apex trigger. If this is correct, can someone provide me the code or other suggestions?

Thanks

Steve
logontokartiklogontokartik
You need to write a trigger on a Task that is created when Quote is emailed. Something like this. 
 
trigger TaskQuoteTrigger on Task (after insert) {

// Since tasks are generic, you need to make sure that you get only the ones created by quote email
   for (Task tsk : Trigger.new) {
         if(tsk.WhatId.getSobjectType().getDescribe().getName() == 'Quote' && tsk.Status=='Completed' && tsk.Subject.contains('Email')) // you can add any conditions here, you need to get quoteids.
         quoteIds.add(tsk.WhatId); 
   }

   for (Quote qt : [Select Id, OpportunityId from Quote where Id in : quoteIds]){
       Opportunity opp = new Opportunity(Id=qt.OpportunityId,StageName='Proposal/Price Quote Sent');
       opportunitiesToUpd.add(opp);
  }

  update opportunitiesToUpd;
}


 
Steve HarrisonSteve Harrison
Thanks Kartik. I'm getting a compilation error on line 9 saying that quoteids is invalid. Any thoughts? Your help is much appreciated! Steve
David @ ConfigeroDavid @ Configero
trigger TaskQuoteTrigger on Task (after insert) {
	Set<Id> quoteIds = new Set<Id>();
	Map<Id, Opportunity> opportunitiesToUpdate = new Map<Id, Opportunity>();

// Since tasks are generic, you need to make sure that you get only the ones created by quote email
	for (Task task : Trigger.new) {
		if (task.WhatId.getSobjectType().getDescribe().getName() == 'Quote' 
		&& task.Status == 'Completed' 
		&& (String.isNotEmpty(task.Subject) && task.Subject.contains('Email'))) { // you can add any conditions here, you need to get quoteids.
			quoteIds.add(task.WhatId);
		}
	}

	if (quoteIds.isEmpty()) {
		return;
	}

	for (Quote quote : [Select OpportunityId from Quote where Id in :quoteIds]) {
		Opportunity opportunity = new Opportunity(
			Id = quote.OpportunityId, 
			StageName = 'Proposal/Price Quote Sent'
			);

		opportunitiesToUpdate.put(Id, opportunity);
	}

	update opportunitiesToUpdate.values();
}

Based on your previous feedback, here is the code submitted with compile errors.  You were missing two variables on lines #2 and #3.

This code is cleaned up a bit and fixes a few bugs in the previous code.  There is one final assumption here.  The code previously submitted does not handle after update, which I recommend you handling.  Not all Tasks are created directly as 'Completed', and they are updated (sometimes multiple times) before reaching a Completed status.  You will want to add the 'after update' event and check that your fields have changed from your previous task's values compared to the current task's values.  Look at Trigger.oldMap and do something similar to Task oldTask = Trigger.oldMap.get(task.Id); to get the previous task's values/state for your comparison purposes.  This way you are not blindly running updates on Opportunities that might not need it when driving fields have not been changed.