[SalesForce] Trigger to update field on Account, on related opportunities, which is a custom lookup from Account to Opportunity

I have the below trigger to update count of Opportunities not equal to Stagename closed on the account page field Count_Of_Projects_Not_Lost__c

The below trigger is working for Deletes,inserts and if from opportunities the account association is removed.

But for testing purpose, if I change a opportunity from '9-Closed' to any other Open value, the count of project number is not getting updated

Can you please give me some pointers regarding this

trigger CountProjectonAccounts on Opportunity (after insert, after delete,after undelete,after update) {


    Set<Id> aId = new Set<Id>();

if(Trigger.isInsert || Trigger.isUndelete){
    for(Opportunity opp : Trigger.New){
        aId.add(opp.Oppor_Existing_Hotel_Plot_Portfolio__c);
    }
    List<Account> acc = [select id,Count_Of_Projects_Not_Lost__c from Account where Id in:aId];
    List<Opportunity> con = [select id from Opportunity where StageName!='9- Lost' and Oppor_Existing_Hotel_Plot_Portfolio__c in :aId];

    for(Account a : acc){
        a.Count_Of_Projects_Not_Lost__c=con.size();

    }update acc;
}

if(Trigger.isDelete){
    for(Opportunity opp : Trigger.old){
        aId.add(opp.Oppor_Existing_Hotel_Plot_Portfolio__c);
    }
    List<Account> acc = [select id,Count_Of_Projects_Not_Lost__c from Account where Id in:aId];
    List<Opportunity> con = [select id from Opportunity where StageName!='9- Lost' and Oppor_Existing_Hotel_Plot_Portfolio__c in :aId];

    for(Account a : acc){
        a.Count_Of_Projects_Not_Lost__c=con.size();

    }update acc;
}

if(Trigger.isUpdate){
   Set<Id> OldAId = new Set<Id>(); 
    for(Opportunity opp : Trigger.new){
    if(opp.Oppor_Existing_Hotel_Plot_Portfolio__c != Trigger.oldMap.get(opp.id).Oppor_Existing_Hotel_Plot_Portfolio__c)
        aId.add(opp.Oppor_Existing_Hotel_Plot_Portfolio__c);
        OldAId.add(Trigger.oldMap.get(opp.id).Oppor_Existing_Hotel_Plot_Portfolio__c);

    }
    if(!aId.isEmpty()){
    //for new Accounts
    List<Account> acc = [select id,Count_Of_Projects_Not_Lost__c from Account where Id in:aId];
    //For New Account Contacts
    List<Opportunity> con = [select id from Opportunity where StageName!='9- Lost' and Oppor_Existing_Hotel_Plot_Portfolio__c in :aId];

    /*
    This is For Old Contacts Count
                          */

    //for Old Accounts
    List<Account> Oldacc = [select id,Count_Of_Projects_Not_Lost__c from Account where Id in:OldAId];

    //For Old Account Contacts
    List<Opportunity> OldCon = [select id from Opportunity where StageName!='9- Lost' and Oppor_Existing_Hotel_Plot_Portfolio__c in :OldAId];

    //For New Accounts
    for(Account a : acc){
        a.Count_Of_Projects_Not_Lost__c=con.size();


    }update acc;

    //For Old Accounts
    for(Account a : Oldacc){
        a.Count_Of_Projects_Not_Lost__c=OldCon.size();

    }update Oldacc;
    }
}
}

Best Answer

I think you have a logic problem in addition to your what you state. The logic problem is that you are not associating the account being updated with the collection of opportunities. That will be problematic when you have more than one account in the collection.

I changed your code to be cleaner (less repetition) to adjust your logic problem and to solve your stated issue (you have to check if the stage changed, not only if the portfolio changed)

trigger CountProjectonAccounts on Opportunity (after insert, after delete,after undelete,after update) {


    Set<Id> aId = new Set<Id>();
    List<Opportunity> oppsToIterate;

    if(Trigger.isInsert || Trigger.isUpdate || Trigger.isUndelete) {
        oppsToIterate = trigger.new;
    } else if(Trigger.isDelete){
        oppsToIterate = trigger.old;  
    }

    for(Opportunity opp : oppsToIterate){
        if (! trigger.isUpdate) {
            aId.add(opp.Oppor_Existing_Hotel_Plot_Portfolio__c);
        } else if (opp.Oppor_Existing_Hotel_Plot_Portfolio__c != Trigger.oldMap.get(opp.id).Oppor_Existing_Hotel_Plot_Portfolio__c ||
                   opp.StageName != Trigger.oldMap.get(opp.id).StageName) {
            aId.add(opp.Oppor_Existing_Hotel_Plot_Portfolio__c);
            aId.add(Trigger.oldMap.get(opp.id).Oppor_Existing_Hotel_Plot_Portfolio__c);
        }

    }

    //Check the name `Oppor_Existing_Hotel_Plot_Portfolios__r` to make sure it matches your actual relationship name
    List<Account> acc = [select id,Count_Of_Projects_Not_Lost__c, (Select Id from Opportunities where StageName!='9-Lost') from Account where Id in:aId];

    for(Account a : acc){
        a.Count_Of_Projects_Not_Lost__c = a.Opportunities.size();

    }
    update acc;

}
Related Topic