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
Sreelakshmi AsokanSreelakshmi Asokan 

trigger to populate the account field with opportunity having max amount

Hi,

I have a field in Account as Top_Opportunity__c which is a lookup to opportunity. I need to write a trigger to populate the same field with the child opportunity having maximum Amount (In all after triggers).

Can someone please help me with this. Thanks in advance:)
Best Answer chosen by Sreelakshmi Asokan
SubratSubrat (Salesforce Developers) 
Hello Sreelakshmi ,

Please try with the below :
trigger UpdateAccountTopOpportunity on Opportunity (after insert, after update, after delete) {
    
    Set<Id> accountIds = new Set<Id>();
    
    // Collect all the account Ids associated with the opportunities being inserted, updated or deleted
    for(Opportunity opp : Trigger.new) {
        accountIds.add(opp.AccountId);
    }
    for(Opportunity opp : Trigger.old) {
        accountIds.add(opp.AccountId);
    }
    
    // Query all the child opportunities for each account and find the one with maximum amount
    Map<Id, Opportunity> accountTopOppMap = new Map<Id, Opportunity>();
    for(Account acc : [SELECT Id, (SELECT Id, Amount FROM Opportunities ORDER BY Amount DESC LIMIT 1) 
                       FROM Account WHERE Id IN :accountIds]) {
        if(acc.Opportunities.size() > 0) {
            accountTopOppMap.put(acc.Id, acc.Opportunities[0]);
        }
    }
    
    // Update the Top_Opportunity__c field on the corresponding accounts
    List<Account> accountsToUpdate = new List<Account>();
    for(Opportunity opp : Trigger.new) {
        Account acc = new Account(Id = opp.AccountId);
        if(accountTopOppMap.containsKey(opp.AccountId)) {
            acc.Top_Opportunity__c = accountTopOppMap.get(opp.AccountId).Id;
        }
        accountsToUpdate.add(acc);
    }
    for(Opportunity opp : Trigger.old) {
        Account acc = new Account(Id = opp.AccountId);
        if(accountTopOppMap.containsKey(opp.AccountId)) {
            acc.Top_Opportunity__c = accountTopOppMap.get(opp.AccountId).Id;
        }
        accountsToUpdate.add(acc);
    }
    
    if(accountsToUpdate.size() > 0) {
        update accountsToUpdate;
    }
}


If it helps please mark this as Best Answer.
Thank you.

All Answers

SubratSubrat (Salesforce Developers) 
Hello Sreelakshmi ,

Please try with the below :
trigger UpdateAccountTopOpportunity on Opportunity (after insert, after update, after delete) {
    
    Set<Id> accountIds = new Set<Id>();
    
    // Collect all the account Ids associated with the opportunities being inserted, updated or deleted
    for(Opportunity opp : Trigger.new) {
        accountIds.add(opp.AccountId);
    }
    for(Opportunity opp : Trigger.old) {
        accountIds.add(opp.AccountId);
    }
    
    // Query all the child opportunities for each account and find the one with maximum amount
    Map<Id, Opportunity> accountTopOppMap = new Map<Id, Opportunity>();
    for(Account acc : [SELECT Id, (SELECT Id, Amount FROM Opportunities ORDER BY Amount DESC LIMIT 1) 
                       FROM Account WHERE Id IN :accountIds]) {
        if(acc.Opportunities.size() > 0) {
            accountTopOppMap.put(acc.Id, acc.Opportunities[0]);
        }
    }
    
    // Update the Top_Opportunity__c field on the corresponding accounts
    List<Account> accountsToUpdate = new List<Account>();
    for(Opportunity opp : Trigger.new) {
        Account acc = new Account(Id = opp.AccountId);
        if(accountTopOppMap.containsKey(opp.AccountId)) {
            acc.Top_Opportunity__c = accountTopOppMap.get(opp.AccountId).Id;
        }
        accountsToUpdate.add(acc);
    }
    for(Opportunity opp : Trigger.old) {
        Account acc = new Account(Id = opp.AccountId);
        if(accountTopOppMap.containsKey(opp.AccountId)) {
            acc.Top_Opportunity__c = accountTopOppMap.get(opp.AccountId).Id;
        }
        accountsToUpdate.add(acc);
    }
    
    if(accountsToUpdate.size() > 0) {
        update accountsToUpdate;
    }
}


If it helps please mark this as Best Answer.
Thank you.
This was selected as the best answer
Bryan Leaman 6Bryan Leaman 6
Excellent answer, Subrat. My only suggestions are that the trigger should only update the account *IF* the opportunity changes from what it already is set to. That way other updates to the highest value opportunity don't automatically always update the account record again. Also, I believe if an opportunity is re-parented and the old account has no other opportunities, it may not remove the reference.
// Make sure you store null as the largest opportunity Id if an account is re-parented and has no opportunities 
// *or* if the op needs to add logic to only select open opportunities and an opportunity closes and
// needs to be removed from the account's largest opportunity reference
.... // change this:
        if(acc.Opportunities.size() > 0) { 
            accountTopOppMap.put(acc.Id, acc.Opportunities[0]);
        }
... // to this:
        if(acc.Opportunities.size() > 0) {
            accountTopOppMap.put(acc.Id, acc.Opportunities[0]);
        } else {
            accountTopOppMap.put(acc.Id, null);
        }

//-----------------------------------------------------------------------------------

// To only update accounts when the opportunity reference changes, 
// I suggest changing this section (in both loops -- trigger.New & trigger.Old:
        Account acc = new Account(Id = opp.AccountId);
        if(accountTopOppMap.containsKey(opp.AccountId)) {
            acc.Top_Opportunity__c = accountTopOppMap.get(opp.AccountId).Id;
        }
        accountsToUpdate.add(acc);
...

// to this:
        Account acc = new Account(Id = opp.AccountId);
        if(accountTopOppMap.containsKey(opp.AccountId)) {
            Id oppId = accountTopOppMap.get(opp.AccountId).Id;
            // only update the account if the opportunity Id changes
            if (acc.Top_Opportunity__c!=oppId) {
                acc.Top_Opportunity__c = oppId;
                accountsToUpdate.add(acc);
            }
        } 
...