I'm stumped by this, because there may be multiple triggers fired. Really what I want is a trigger on the opp when any related opportunitysplit is inserted, updated, or deleted (that's how OpportunityLineItem works). But OpportunitySplit does not seem to fire Opportunity triggers.

I can't figure out how to use the OpportunitySplit trigger, because multiple triggers may fire (insert, update, delete), and I only want to send one email when any aspect of the OpportunitySplit changes.

  • Are you having problems when the trigger fires for both deleting and inserting OpportunitySplit records against the same Opportunity in one transaction? Typically in cases like that you would track the Opportunity Id's that have been processed for notification. Jan 10 '19 at 1:38
  • yes, that's the problem, but since multiple triggers may fire (opportunitysplit after insert, after update, after delete), how can I know when all of the pending trigger have fired (they will be in one execution context), so that I know I can go ahead and update the parent opps?
    – Bo Laurent
    Jan 10 '19 at 4:07

One way to approach this is to delay the required action until after the transaction has completed. In some ways you don't care about the specific OpportunitySplit records that are being inserted/updated/deleted. You only care about the Opportunity that they belong to.

One way to do this is to have a flag on the Opportunity that indicates it needs to be processed. Then, in the OpportunitySplit trigger you just build up a list of Opportunity Id's that need to be processed. At the end of the trigger you update all the Opportunities at once to set the flag on.

A scheduled batch job is searching for any Opportunity records where the flag is on. When it finds one it exams the current OpportunitySplit records and performs the required actions.

  • Yes, I thought of that, but I would rather avoid that complexity.
    – Bo Laurent
    Jan 12 '19 at 1:15

I realized that I wanted to perform just one update operation, and that was preventing me from a solution that updates each opp only once, but might have three update operations. I use the static set processedOppIds to remember which opps have already been processed in the execution context.

The following code works (tested). It is called from the insert, update, and delete triggers. I use the field Opportunity_Team_Notify_Trigger__c to trigger the email in a process builder component.

It would be nice if apex had a way to perform an operation just before the execution context is destroyed. Then I could do just a single update, and I could also create some text that describes all of the changes.

public with sharing class OpportunityTeamNotifyHelper {
    @testvisible static Set<Id> processedOppIds = new Set<Id>();

    // after insert, after update, after delete
    public static void splits(OpportunitySplit[] splits) {
        Set<Id> oppIds = gatherIdsToProcess(splits, processedOppIds);

        Opportunity[] opps = [select Id, Opportunity_Team_Notify_Trigger__c 
                              from Opportunity 
                              where Id in :oppIds];
        for (Opportunity opp : opps) {
            opp.Opportunity_Team_Notify_Trigger__c += 1;
        update opps;

    @testvisible static Set<Id>  gatherIdsToProcess(OpportunitySplit[] splits, Set<Id> exceptIds) {
        Set<Id> oppIds = new Set<Id>();

        for (OpportunitySplit split : splits) {
            Id opportunityId = split.OpportunityId;
            if (exceptIds.contains(opportunityId) == False) {

        return oppIds;


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.