0

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;
    }
}
}
  • Just use dlrs, then you don't need any of your own Apex. – Adrian Larson Feb 22 '16 at 17:47
  • @AdrianLarson - Fields on Opportunity can be RSF'd to Account; why DLRS? – cropredy Feb 22 '16 at 18:56
  • @crop1645 didn't think about if it was m/d, figured they would have thought of that. – Adrian Larson Feb 22 '16 at 18:58
1

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;

}
  • Hi Sebastian, Thank you very much for your feedback..But when i run the trigger mentioned by you i got the below error "Didn't understand relationship 'Oppor_Existing_Hotel_Plot_Portfolios__r' in FROM part of query call. If you are attempting to use a custom relationship, be sure to append the '__r' after the custom relationship name. Please reference your WSDL or the describe call for the appropriate names." Line:25 – samcool Feb 22 '16 at 18:28
  • Look at my comment above that line. I don't know what you've named your relationship. To see the actual name, go to the Count_Of_Projects_Not_Lost__c field on the Opportunity object, and see the "Child Relationship Name" field. Then simply put that name in the proper places in the code. – Sebastian Kessel Feb 22 '16 at 18:36
  • @sebastian..Thanks.. Count_Of_Projects_Not_Lost__c is a field on the Account Page. I have put the correct relationship name Opportunities__r and the code compiles perfectly.. But it counts all opportunities and doesn't take Stagename in consideration.. – samcool Feb 22 '16 at 18:54
  • Ooops. I should've seen that. Apologies. I've updated my code. Please check that the SELECT statement in your code looks exactly like mine. The "where" clause for opportunities must be within the subquery – Sebastian Kessel Feb 22 '16 at 19:01
  • And, if this helps you, don't hesitate to mark the question as accepted so others can see this exchange and benefit from the answer – Sebastian Kessel Feb 22 '16 at 19:12
0

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;

}

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.