i have a custom filed on Account Name(AssignCheckBox) ,write a Trigger on Opportunity when i update Stage of Opportunity is closed Lost and AccountId not Null and if Selected Account Might be possible selected Account have more than one Opportunity then i have to check all related Opportunity will be Closed Lost then Account CheckBox will be true other wise trigger will not be fire

please guide me how to do

public class OppPrintCampaign{
public static void InsertOpp(List<Opportunity> lstopp ,Map<Id,Opportunity> mapIdToSatge){
    Map<Id,Id> mapAccIdToOppId = new Map<Id,Id>();
    Set<Id> setOfAccId = New Set<Id>();
    Set<Id> setOfOppId = New Set<Id>();
    List<Account> lstacc = New List<Account>();
    Boolean check = false;
    //Campaign objcamp = [Select Id,name from campaign where Id = '7012v000002KBp9'];
    for(Opportunity objopp:lstopp){
        if(objopp.accountId !=null && objopp.stageName == 'Closed Lost' && objopp.stageName != mapIdToSatge.get(objopp.Id).stageName){
     for(Opportunity objopp :[Select Id,Name ,Stagename ,AccountId from Opportunity where AccountId IN:setOfAccId]){        
         if(objopp.StageName == 'Closed Lost'){
             check = true;
     for(Account objacc:[Select Id,Name from Account where Id IN:setOfAccId]){
         if(check == true){
         objacc.Assign_Engments__c = true;
    update lstacc;


above is my code but didn't work in above scenario if account has more than one opportunity and stage of opportunity is not closed then account checkbox becomes true that should not be true

so please guide where i change my code


1 Answer 1


Your logic here:

     if(objopp.StageName == 'Closed Lost'){
         check = true;

is incorrect for two reasons.

  1. This is an "any" operation, rather than an "all". That is, your check variable will be true if any Opportunity is Closed Lost, but you've stated that you want it to be true only if all Opportunities are Closed Lost.

    If you want to track whether all Opportunities are Closed Lost, you'd want to start whatever variable you're using to track with the value true and set it to false if you locate any Opportunity that is not Closed Lost. However, making that change here is not enough to solve your problem; see the next item.

  2. You are iterating over all of the Opportunities associated with all Accounts that have Opportunities in the trigger set, and you are not distinguishing between Opportunities associated with different Accounts.

    There are multiple ways to solve this, but what they all have in common is building the right data structure to track these Opportunities. One approach would be to iterate over the Opportunities and sort them into a Map<Id, List<Opportunity>> keyed on the AccountId, then iterating over that map's keySet() (the set of Account Ids) and in an inner loop iterating over the corresponding List<Opportunity> to find the total for each Account. In loose pseudocode,

     create a Map<Id, List<Opportunity>>
     for (each Opportunity in query) {
         if (map does not contain Opportunity's Account Id) {
             add a new List<Opportunity> with that key
         add this Opportunity to the list keyed under its Account Id
    for (each AccountId in map's keySet()) {
        Boolean check = true;

        for (each Opportunity in this Account's list from the Map) {
           if (this Opportunity is not Closed Lost) {
               check = false;
        add this Account and check value to a list to be updated
    update all Accounts

Obviously you will need to do some adaptation to fit into your code and translate into actual Apex.

The final observation I have is that it's not clear that what looks like an after insert trigger is the right place, or the only right place, to run this kind of code. You probably also need an update trigger.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .