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
NightShadeNightShade 

Urgent Help with a Trigger

Hey ,

Need help with a trigger . Below is a trigger on products which is not firing at all i checked the debug log also and its not there . Once a opportunity is Won or Won-Future Activation date and the product code contains 'FF' the trigger should fire and Update a field on account called Fit Finder Status to 'Active'.The thing is products and opportunities are not directly related although products are shown under a related list under Opportunities.There are also Pricebook and PricebookEntry in the schema .PricebookEntry is related to Opportunities.The Code saves without errors . Can anyone please help since I am still new to these kind of triggers.

 

Thanks and Regards

 

 

trigger FFStatusA on Product2 (after update , after insert ) {

ID ID1;
ID ID2;
ID ID3;
ID ID4;
   Opportunity O = [ Select AccountId , Pricebook2Id from Opportunity  where Pricebook2Id =:ID4];


ID1=O.AccountId;

ID2=O.Pricebook2Id;

PricebookEntry Pe = [Select Pricebook2Id , ProductCode from PricebookEntry where Pricebook2Id=:ID2];
  ID3 = Pe.Pricebook2Id;
 
 Account acc = [Select  Id , Name  from Account where Id  =:ID1];
 ID4 = Acc.Id;
   
    String pc = Pe.ProductCode;
  String f ='FF';
  Boolean Result = pc.Contains(f);
 
 
for (Product2 p :Trigger.new){
 
 
 
//If (acc.Id ==o.AccountId && Pe.Pricebook2Id ==O.Pricebook2Id  ){
 // && Result == True
 
 
 If ( (O.StageName== 'Won' || O.StageName=='Won - Future Activation Date' )&& Result == True  ){
   
    
    acc.Fit_Finder_Status__pc = 'Active';
    
    }
    
 //   }
    }
    database.update(acc);
    
    
}
aalbertaalbert

It sounds like you want this trigger to be on the Opportunity object and not the Product2 object. The initiating event is when the opportunity is inserted/update with a StageName of "Won" or "Won Future Activation" (or something like that). From there, the trigger can query the related products to verify if the specific FF product is associated. Then complete its logic. 

 

 

JimRaeJimRae

I would agree with aalbert about this being an Opportunity trigger, not a Product2 trigger.

That being said, you also have an execution order issue that will cause your trigger never to update any record.

You initize an ID variable called ID4, then, on the next line, you do a soql query for an opportunity where the pricebookid = ID4, but ID4 has no value yet. This would cause your Opportunity "O" to be null.  Also, the way this soql is constructed, it is likely that you will get more than one opportunity returned with the same pricebookid, and you cannot set a single Opportunity equal to a list result.

 

NightShadeNightShade

Hi Aalbert /Jim ,

 

Sorry for not replying earlier , since the issue was on hold. I had actually tried writing the trigger on Opportunity earlier but the trigger gave me a null pointer exception when I tried querying the Product Object saying no product was available, which I believe is due to the fact that we are associating an Opportunity with a product once an opportunity is created . Please correct me If I am missing something since I am not very experienced at this level of apex coding . Would it help if I were to write the trigger on Opportunity Product ?? 

 

Thanks and Regards

JimRaeJimRae

This is a bit of a tricky scenario.  If you use trigger on the OLI then it wouldn't fire when the FF product exists and the stage is changed to the Won or Future-Won, unless you had other rules in place that prevented products from being added or changed when the opportunity was in these stages.

I would still suggest that you use an Opportunity trigger, you should only need after update because after insert, there would never be any products included.

If I remember correctly, adding a product will still cause the opportunity update trigger to fire.  If you post the code you have for the Opportunity trigger, it would be easier to debug.

NightShadeNightShade

Hi Jim,

 

I will post my code in little while from now .But I had another query which came up  , i noticed through the Salesforce Schema in Eclipse that the Product and Opportunity are not directly related to each other , is there some other way of relating them and then querying for the Product Code ?

 

Thanks a ton !!

JimRaeJimRae

You are correct that the "Product' is not related directly to the opportunity.  Each Opportuntiy will have 0 or more OpportunityLineItems (OLI), each of these OLIs will have a PricebooEntryID.  The PricebookEntry object will have a Product2ID, which is how the product is related to the opportunity.  This is done so a single product can have many different pricing options defined, and based on which pricebooks are shared to the user, different pricing is displayed.

 

So, you will need to do some relational queries and possibly some maps to get from the Opportunity to the Product.

NightShadeNightShade

Thanks a lot JIm for explaining the relationships ,I really appreciate your help. Another query I had was are Opportunity Products and Opportunity Line Item the same thing , the reason I ask is when I was writing a trigger under Opportunity Products  the first line on the trigger was , trigger triggername on OpportunityLineItem  instead of Opportunity Products . Also one more thing I noticed that the Product Code was a Standard Field in Opportunity Product but when I tried to retrieve the Product Code using a SOQL query on Opportunity LineItem in the trigger I wrote under Opportunity Products it gave me an error saying No such column existed on Opportunity Line Item. Would have any idea on these ?

 

 

Thanks and Best Regards

 

JimRaeJimRae

Yes, Opportunity Product (shown via the UI) is called OpportunityLineItem via Apex.  As for the Product Code on the Opportunity Product, I think that SFDC is doing some internal mapping of the field, that is why you see it in the UI, but not in APEX.

You can get to it with a relational query:

 

 

Select o.PricebookEntryId, o.PricebookEntry.ProductCode from OpportunityLineItem o

 

 

but I am not positive if that product code and the one on the product2 object are the same.

Give it a try and see if you are getting what you might expect.

 

 

NightShadeNightShade

Hi Jim

 

I wrote my Trigger as below on the Opportunity as we discussed . But it is giving me a NullPointerException at below line . Can you please help me .


Thanks and Regards

 

 

 

trigger FFStatus on Opportunity (after update) {

Opportunity Opp;

List <OpportunityLineItem> OLIPEMAP  = new List <OpportunityLineItem> ();

 

OLIPEMAP = [Select o.PricebookEntryId ,o.PricebookEntry.ProductCode from OpportunityLineItem o where o.OpportunityId =: Opp.Id ]; <---here is the Exception
 
 
 
 for (Opportunity Op :Trigger.new){
 
 
  for (  OpportunityLineItem oli : OLIPEMAP ){
 
  String pc = Oli.PricebookEntry.ProductCode;
  String f ='FF';
  Boolean Result = pc.Contains(f);
 If ( (Op.StageName== 'Won' || Op.StageName=='Won - Future Activation Date' ) && Result == True ){
    
    
    Account a;
   
    
    a.Fit_Finder_Status__c = 'Active';
    
    }
    
    }
    }
}

JimRaeJimRae

Well, to start with, the reason you are getting the null pointer is becase your opportunity Opp is not defined to anything. You have declared an Opportunity variable called Opp, but it is assigned to any existing opportunity.  You did the same type of thing with the Account object.

You need to use the Trigger.new list to reference the actual opportunity or opportunties that caused the trigger to fire in the first place.

 

See how this works for you:

 

 

trigger FFStatus on Opportunity (after update) {
	String f ='FF';
	Set<ID> OppIDs = new Set<ID>();
	Set<ID> AcctIDs = new Set<ID>();
	for(Opportunity o:Trigger.New){
		OppIDs.add(o.id);
		AcctIDs.add(o.accountid);
	}
	Map<ID,Account> ACCTMAP = new Map<ID,Account>();  //create a map list of accounts with the Account ID as the key
	ACCTMAP= [select id,Fit_Finder_Status__c from Account where id in:AcctIDs];
	
	List<Account> updACCT = new List<Account>(); //accounts in this list will get updated
	
	Map <ID,List<OpportunityLineItem>> OLIOPPMAP  = new Map <ID,List<OpportunityLineItem>> (); //create a map list of OLI with the Opportunity ID as the key, note that each opp could have more than one OLI
	for(OpportunityLineItem oli: [Select o.PricebookEntryId ,o.PricebookEntry.ProductCode from OpportunityLineItem o where o.OpportunityId in :Trigger.New ]){
		if(OLIOPPMAP.containsKey(oli.OpportunityID){
			OLIOPPMAP.get(oli.OpportunityID).add(oli);
		}else{
			OLIOPPMAP.put(oli.OpportunityID,new List<OpportunityLineItem>{oli};
		}
	}
 
	for (Opportunity Op :Trigger.new){
 
 
		for (  OpportunityLineItem oli : OLIOPPMAP.get(Op.id) ){
 
			String pc = oli.PricebookEntry.ProductCode;
			Boolean Result = pc.Contains(f);
			if ( (Op.StageName== 'Won' || Op.StageName=='Won - Future Activation Date' ) && Result == True ){
				Account tmpAccount = ACCTMAP.get(Op.AccountID);
				tmpAccount.Fit_Finder_Status__c = 'Active';
				updACCT.add(tmpAccount);
			}
		}
    }
	try{
		update updACCT;
	}catch(DMLException d){
		system.debug('\n\nERROR UPDATING ACCOUNTS: '+d.getDMLMessage(0));
	}
}

 

 

NightShadeNightShade

Hi Jim,

 

I actually got an error for the below line as follows ,

 

Best Regards

 

Error :

llegal assignment from LIST<Account> to MAP<Id,Account> at line 10 column 5


 

 Map<ID,Account> ACCTMAP = new Map<ID,Account>();  //create a map list of accounts with the Account ID as the key
    ACCTMAP= [select id,Fit_Finder_Status__c from Account where id in:AcctIDs];

JimRaeJimRae

That should have worked.  I am just typing this in, so you may need to do some clean up to get it to compile.

 

Try it this way:

 

trigger FFStatus on Opportunity (after update) {
	String f ='FF';
	Set<ID> OppIDs = new Set<ID>();
	Set<ID> AcctIDs = new Set<ID>();
	for(Opportunity o:Trigger.New){
		OppIDs.add(o.id);
		AcctIDs.add(o.accountid);
	}
	Map<ID,Account> ACCTMAP = new Map<ID,Account>([select id,Fit_Finder_Status__c from Account where id in:AcctIDs]);  //create a map list of accounts with the Account ID as the key
	
	
	List<Account> updACCT = new List<Account>(); //accounts in this list will get updated
	
	Map <ID,List<OpportunityLineItem>> OLIOPPMAP  = new Map <ID,List<OpportunityLineItem>> (); //create a map list of OLI with the Opportunity ID as the key, note that each opp could have more than one OLI
	for(OpportunityLineItem oli: [Select o.PricebookEntryId ,o.PricebookEntry.ProductCode from OpportunityLineItem o where o.OpportunityId in :Trigger.New ]){
		if(OLIOPPMAP.containsKey(oli.OpportunityID){
			OLIOPPMAP.get(oli.OpportunityID).add(oli);
		}else{
			OLIOPPMAP.put(oli.OpportunityID,new List<OpportunityLineItem>{oli};
		}
	}
 
	for (Opportunity Op :Trigger.new){
 
 
		for (  OpportunityLineItem oli : OLIOPPMAP.get(Op.id) ){
 
			String pc = oli.PricebookEntry.ProductCode;
			Boolean Result = pc.Contains(f);
			if ( (Op.StageName== 'Won' || Op.StageName=='Won - Future Activation Date' ) && Result == True ){
				Account tmpAccount = ACCTMAP.get(Op.AccountID);
				tmpAccount.Fit_Finder_Status__c = 'Active';
				updACCT.add(tmpAccount);
			}
		}
    }
	try{
		update updACCT;
	}catch(DMLException d){
		system.debug('\n\nERROR UPDATING ACCOUNTS: '+d.getDMLMessage(0));
	}
}

 

 

NightShadeNightShade

hey Jim,

 

I am sorry if i am troubling you too much but i am not sure why i am getting the below error .

 

Thanks and Regards

 

 

 

System.NullPointerException: Attempt to de-reference a null object: Trigger.FFStatus: line 26, column

 

 

 

   for (Opportunity Op :Trigger.new){


        for (  OpportunityLineItem oli : OLIOPPMAP.get(Op.id) ){     <<--------- Here is the Exception
 
            String pc = oli.PricebookEntry.ProductCode;
            Boolean Result = pc.Contains(f);
            if ( (Op.StageName== 'Won' || Op.StageName=='Won - Future Activation Date' ) && Result == True ){
                Account tmpAccount = ACCTMAP.get(Op.AccountID);
                tmpAccount.Fit_Finder_Status__c = 'Active';
                updACCT.add(tmpAccount);
            }
        }
    }

JimRaeJimRae

My guess would be that you have an Opportunity being updated that has no products at all.

This error handling should catch that scenario (basically, ignore any opportunities with no products added:

 

 

trigger FFStatus on Opportunity (after update) {
	String f ='FF';
	Set<ID> OppIDs = new Set<ID>();
	Set<ID> AcctIDs = new Set<ID>();
	for(Opportunity o:Trigger.New){
		OppIDs.add(o.id);
		AcctIDs.add(o.accountid);
	}
	Map<ID,Account> ACCTMAP = new Map<ID,Account>([select id,Fit_Finder_Status__c from Account where id in:AcctIDs]);  //create a map list of accounts with the Account ID as the key
	
	
	List<Account> updACCT = new List<Account>(); //accounts in this list will get updated
	
	Map <ID,List<OpportunityLineItem>> OLIOPPMAP  = new Map <ID,List<OpportunityLineItem>> (); //create a map list of OLI with the Opportunity ID as the key, note that each opp could have more than one OLI
	for(OpportunityLineItem oli: [Select o.PricebookEntryId ,o.PricebookEntry.ProductCode from OpportunityLineItem o where o.OpportunityId in :Trigger.New ]){
		if(OLIOPPMAP.containsKey(oli.OpportunityID){
			OLIOPPMAP.get(oli.OpportunityID).add(oli);
		}else{
			OLIOPPMAP.put(oli.OpportunityID,new List<OpportunityLineItem>{oli};
		}
	}
 
	for (Opportunity Op :Trigger.new){
 
		if(OLIOPPMAP.containsKey(Op.id){
			for (  OpportunityLineItem oli : OLIOPPMAP.get(Op.id) ){
 
				String pc = oli.PricebookEntry.ProductCode;
				Boolean Result = pc.Contains(f);
				if ( (Op.StageName== 'Won' || Op.StageName=='Won - Future Activation Date' ) && Result == True ){
					Account tmpAccount = ACCTMAP.get(Op.AccountID);
					tmpAccount.Fit_Finder_Status__c = 'Active';
					updACCT.add(tmpAccount);
				}
			}
		}
    }
	try{
		update updACCT;
	}catch(DMLException d){
		system.debug('\n\nERROR UPDATING ACCOUNTS: '+d.getDMLMessage(0));
	}
}

 

 

NightShadeNightShade

Actually the above error was when  I was inserting(creating) a new opportunity .That one disappeared and now when I tried adding a product it gave me the below error .

 

Error :

SObject row was retrieved via SOQL without querying the requested field: OpportunityLineItem.OpportunityId: Trigger.FFStatus: line 16, column 34 

 

 

 

 

 

List<Account> updACCT = new List<Account>(); //accounts in this list will get updated
    
    Map <ID,List<OpportunityLineItem>> OLIOPPMAP  = new Map <ID,List<OpportunityLineItem>> (); //create a map list of OLI with the Opportunity ID as the key, note that each opp could have more than one OLI
    for(OpportunityLineItem oli: [Select o.PricebookEntryId ,o.PricebookEntry.ProductCode from OpportunityLineItem o where o.OpportunityId in :Trigger.New ]){
        if(OLIOPPMAP.containsKey(oli.OpportunityID)) {     <<<----------------- Here is the exception.
            OLIOPPMAP.get(oli.OpportunityID).add(oli);
        }else{
            OLIOPPMAP.put(oli.OpportunityID,new List<OpportunityLineItem>{oli});
        }
    }

JimRaeJimRae

Hopefully, you are starting to get an idea of how this all works by looking at the changes that I have been making to debug the issues.

 

 

trigger FFStatus on Opportunity (after update) {
	String f ='FF';
	Set<ID> OppIDs = new Set<ID>();
	Set<ID> AcctIDs = new Set<ID>();
	for(Opportunity o:Trigger.New){
		OppIDs.add(o.id);
		AcctIDs.add(o.accountid);
	}
	Map<ID,Account> ACCTMAP = new Map<ID,Account>([select id,Fit_Finder_Status__c from Account where id in:AcctIDs]);  //create a map list of accounts with the Account ID as the key
	
	
	List<Account> updACCT = new List<Account>(); //accounts in this list will get updated
	
	Map <ID,List<OpportunityLineItem>> OLIOPPMAP  = new Map <ID,List<OpportunityLineItem>> (); //create a map list of OLI with the Opportunity ID as the key, note that each opp could have more than one OLI
	for(OpportunityLineItem oli: [Select o.PricebookEntryId ,o.PricebookEntry.ProductCode,OpportunityID from OpportunityLineItem o where o.OpportunityId in :Trigger.New ]){
		if(OLIOPPMAP.containsKey(oli.OpportunityID){
			OLIOPPMAP.get(oli.OpportunityID).add(oli);
		}else{
			OLIOPPMAP.put(oli.OpportunityID,new List<OpportunityLineItem>{oli};
		}
	}
 
	for (Opportunity Op :Trigger.new){
 
		if(OLIOPPMAP.containsKey(Op.id){
			for (  OpportunityLineItem oli : OLIOPPMAP.get(Op.id) ){
 
				String pc = oli.PricebookEntry.ProductCode;
				Boolean Result = pc.Contains(f);
				if ( (Op.StageName== 'Won' || Op.StageName=='Won - Future Activation Date' ) && Result == True ){
					Account tmpAccount = ACCTMAP.get(Op.AccountID);
					tmpAccount.Fit_Finder_Status__c = 'Active';
					updACCT.add(tmpAccount);
				}
			}
		}
    }
	try{
		update updACCT;
	}catch(DMLException d){
		system.debug('\n\nERROR UPDATING ACCOUNTS: '+d.getDMLMessage(0));
	}
}

 

 

NightShadeNightShade

Hi Jim,

 

Yes I am understanding the changes you are making to debug the issues and also higly appreciate the time and effort you have taken to help me out here. But I am still not able to figure out how to get rid of these Null pointer Exceptions as I got another one below.Is there a some standard technique to resolve these , since until now by trial and error I was able get rid of most of my errors.

 

 

Thanks and Regards



System.NullPointerException: Attempt to de-reference a null object: Trigger.FFStatus: line 29, column 34 

 

 

 

for (Opportunity Op :Trigger.new){
 
        if(OLIOPPMAP.containsKey(Op.id)){
            for (  OpportunityLineItem oli : OLIOPPMAP.get(Op.id) ){
 
                String pc = oli.PricebookEntry.ProductCode;
                Boolean Result = pc.Contains(f);        <<---------- Null pointer here.
                if ( (Op.StageName== 'Won' || Op.StageName=='Won - Future Activation Date' ) && Result == True ){
                    Account tmpAccount = ACCTMAP.get(Op.AccountID);
                    tmpAccount.Fit_Finder_Status__c = 'Active';
                    updACCT.add(tmpAccount);
                }
            }
        }
    }

 

NightShadeNightShade

Hi Jim,

 

I beleive the Error is due to the fact that the trigger is firing off when I am first trying to insert the first product and I believe the line does not have a product code to assign to string pc and hence the error.

 

 

Regards

 

 

JimRaeJimRae

Null Pointer Exceptions are difficult to address, but not impossible. what you need to do is to look at where the issue is occuring and determine why.  As in your example, you believe you have an OLI with a null Product Code.  Next evaluate why this happened? Do you allow the Product Code to be null in production? Why is your example null?  If you don't allow nulls in this field, it is a test data error, if you do, then you need to account for it in your code, maybe something like this:

 

for (Opportunity Op :Trigger.new){
 
        if(OLIOPPMAP.containsKey(Op.id)){
            for (  OpportunityLineItem oli : OLIOPPMAP.get(Op.id) ){
                String pc;
                if(oli.PricebookEntry.ProductCode<>null){
                     pc = oli.PricebookEntry.ProductCode;
                }else{
                     pc ='';
                }
                Boolean Result = pc.Contains(f);        <<---------- Null pointer here.
                if ( (Op.StageName== 'Won' || Op.StageName=='Won - Future Activation Date' ) && Result == True ){
                    Account tmpAccount = ACCTMAP.get(Op.AccountID);
                    tmpAccount.Fit_Finder_Status__c = 'Active';
                    updACCT.add(tmpAccount);
                }
            }
        }
    }

 

 

NightShadeNightShade

We do allow some product codes to be null I am guessing , since I have not gone through all of them .But the last error seemed to be because I was trying to retrieve the Product before I had added the Product itself. So anyways the code seems to be working fine for now pending testing approval .There was a  additional condition which the business users gave me so I included that and am posting the code below. I wanted to convey my utmost thanks to you, without your patience, effort and help I think I would never have been able to do this . May be someday I can help someone like me and pass on the goodwill. :-))

 

Thanks and Best Regards

 

trigger FFStatus on Opportunity (after update) {
  String f ='FF';
  String r='RT';
    Set<ID> OppIDs = new Set<ID>();
    Set<ID> AcctIDs = new Set<ID>();
    for(Opportunity o:Trigger.New){
        OppIDs.add(o.id);
        AcctIDs.add(o.accountid);
    }
    Map<ID,Account> ACCTMAP = new Map<ID,Account>([select id,Fit_Finder_Status__c from Account where id in:AcctIDs]);  //create a map list of accounts with the Account ID as the key
    
    
    List<Account> updACCT = new List<Account>(); //accounts in this list will get updated
    
   Map <ID,List<OpportunityLineItem>> OLIOPPMAP  = new Map <ID,List<OpportunityLineItem>> (); //create a map list of OLI with the Opportunity ID as the key, note that each opp could have more than one OLI
    for(OpportunityLineItem oli: [Select o.PricebookEntryId ,o.PricebookEntry.ProductCode,OpportunityID from OpportunityLineItem o where o.OpportunityId in :Trigger.New ]){
        if(OLIOPPMAP.containsKey(oli.OpportunityID)){
            OLIOPPMAP.get(oli.OpportunityID).add(oli);
        }else{
            OLIOPPMAP.put(oli.OpportunityID,new List<OpportunityLineItem>{oli});
        }
    }
     for (Opportunity Op :Trigger.new){
 
       if(OLIOPPMAP.containsKey(Op.id)){
            for (  OpportunityLineItem oli : OLIOPPMAP.get(Op.id) ){
                String pc;
                if(oli.PricebookEntry.ProductCode<>null){
                     pc = oli.PricebookEntry.ProductCode;
                }else{
                     pc ='';
                }
                Boolean Result = pc.Contains(f);   
                Boolean ResultR = pc.Contains(r);   
                if ( (Op.StageName== 'Won' || Op.StageName=='Won - Future Activation Date' ) && Result == True ){
                    Account tmpAccount = ACCTMAP.get(Op.AccountID);
                    tmpAccount.Fit_Finder_Status__c = 'Active';
                    tmpAccount.Fit_Finder_Program__c='Paying - Reg Customer';
                    updACCT.add(tmpAccount);

                }else{if ( (Op.StageName== 'Won' || Op.StageName=='Won - Future Activation Date' ) && ResultR == True ){
                    Account tmpAccountR= ACCTMAP.get(Op.AccountID);
                    tmpAccountR.Fit_Finder_Status__c = 'Active';
                    tmpAccountR.Fit_Finder_Program__c='Right Track';
                    updACCT.add(tmpAccountR);
                    }
                }
            }
          }
        }
    
    try{
        update updACCT;
    }catch(DMLException d){
        system.debug('\n\nERROR UPDATING ACCOUNTS: '+d.getDMLMessage(0));
    }
}

NightShadeNightShade

hey Jim,

 

I think I should have waited before the testing was complete , I ran into another exception as below .I had some additional conditions given to me which I added in the code .It worked good couple of times and when I tried to add another Product with FF Product Code to the list which already had an RT Product Code Product , it broke down.

 

Regards

 

 

 

FFStatus: execution of AfterUpdate caused by: System.ListException: Duplicate id in list: 001P000000FEbeqIAD: Trigger.FFStatus: line 61, column 9  

 

 

 

 

 

 if(OLIOPPMAP.containsKey(Op.id)){
            for (  OpportunityLineItem oli : OLIOPPMAP.get(Op.id) ){
                String pc;
                if(oli.PricebookEntry.ProductCode<>null){
                     pc = oli.PricebookEntry.ProductCode;
                }else{
                     pc ='';
                }
                Boolean Result = pc.Contains(f);   
                Boolean ResultR = pc.Contains(r);   
                if ( (Op.StageName== 'Won' || Op.StageName=='Won - Future Activation Date' ) && Result == True ){
                    Account tmpAccount = ACCTMAP.get(Op.AccountID);
                    tmpAccount.Fit_Finder_Status__c = 'Active';
                    tmpAccount.Fit_Finder_Program__c='Paying - Reg Customer'; 
                    updACCT.add(tmpAccount);

                }else{if ( (Op.StageName== 'Won' || Op.StageName=='Won - Future Activation Date' ) && ResultR == True){
                    Account tmpAccountR= ACCTMAP.get(Op.AccountID);
                    tmpAccountR.Fit_Finder_Status__c = 'Active';
                    tmpAccountR.Fit_Finder_Program__c='Right Track'; 
                    updACCT.add(tmpAccountR);
                    } else{if((Op.StageName== 'Won' || Op.StageName=='Won - Future Activation Date' ) && ResultR == True && Result == True ){
                     Account tmpAccountRF= ACCTMAP.get(Op.AccountID);
                    tmpAccountRF.Fit_Finder_Status__c = 'Active';
                    tmpAccountRF.Fit_Finder_Program__c='Right Track'; 
                    updACCT.add(tmpAccountRF); 
                    }
                  }
                }
            }
          }
        }
    
    try{
        update updACCT; <<------ Exception Line
    }catch(DMLException d){
        system.debug('\n\nERROR UPDATING ACCOUNTS: '+d.getDMLMessage(0));
    }
}
JimRaeJimRae

Ah, another bad assumption on my part. I didn't know that an opportunity could have more than one FF product included on it.

The List collection will allow duplicates to be added, but the update method won't allow duplicates to be updated.

What we need to do is to add the items to a Set, which requires uniqueness, and then at the end add the set to a list for updating (we can't update a Set directly.

You will need to create a set of accounts

 

Set<Account> AcctSet = new Set<Account>();

 

 

add the proper accounts in your if statement section, and then add the full set of unique accounts to the list to be updated:

 

 

updACCT.addAll(AcctSet); //get the unique set of accounts to be updated

 I think you might need some work on your if else logic, the way the loop works, you could never have the same OLI with pc contains f and pc contains r, each one could only have one value.  If you need to check for both, this would be much more complex, I am not sure of the logic off the top of my head.

Hopefully, this get's you close, and you can focus on how to clean up the if logic.

Good Luck!!

 

 

NightShadeNightShade

Hi Jim ,

 

Thanks a lot for the suggestions , but I just am not able to get rid of the duplicate Id bug as below. Please can you give me some more pointers since  I am at a loss how to resolve this problem.

 

Thanks and Regards 

 

 

 

FFStatus: execution of AfterUpdate caused by: System.ListException: Duplicate id in list: 001P000000FEbeqIAD: Trigger.FFStatus: line 64, column 9 

 

trigger FFStatus on Opportunity (after update) {
  String f ='FF';
  String r='RT';
    Set<ID> OppIDs = new Set<ID>();
    Set<ID> AcctIDs = new Set<ID>();
    for(Opportunity o:Trigger.New){
        OppIDs.add(o.id);
        AcctIDs.add(o.accountid);
    }
    Map<ID,Account> ACCTMAP = new Map<ID,Account>([select id,Fit_Finder_Status__c from Account where id in:AcctIDs]);  //create a map list of accounts with the Account ID as the key
    
    
    List<Account> updACCT = new List<Account>(); //accounts in this list will get updated
    Set<Account> AcctSet = new Set<Account>();
   Map <ID,List<OpportunityLineItem>> OLIOPPMAP  = new Map <ID,List<OpportunityLineItem>> (); //create a map list of OLI with the Opportunity ID as the key, note that each opp could have more than one OLI
    for(OpportunityLineItem oli: [Select o.PricebookEntryId ,o.PricebookEntry.ProductCode,OpportunityID from OpportunityLineItem o where o.OpportunityId in :Trigger.New ]){
        if(OLIOPPMAP.containsKey(oli.OpportunityID)){
            OLIOPPMAP.get(oli.OpportunityID).add(oli);
        }else{
            OLIOPPMAP.put(oli.OpportunityID,new List<OpportunityLineItem>{oli});
        }
    }
     for (Opportunity Op :Trigger.new){
 
       if(OLIOPPMAP.containsKey(Op.id)){
            for (  OpportunityLineItem oli : OLIOPPMAP.get(Op.id) ){
                String pc;
                if(oli.PricebookEntry.ProductCode<>null){
                     pc = oli.PricebookEntry.ProductCode;
                }else{
                     pc ='';
                }
                Boolean Result = pc.Contains(f);   
                Boolean ResultR = pc.Contains(r);   
               
                if ( (Op.StageName== 'Won' || Op.StageName=='Won - Future Activation Date' ) && Result == True ){
                    Account tmpAccount = ACCTMAP.get(Op.AccountID);
                    tmpAccount.Fit_Finder_Status__c = 'Active';
                    tmpAccount.Fit_Finder_Program__c='Paying - Reg Customer';
                    AcctSet.add(tmpAccount);
                   
                } else{if ( ((Op.StageName== 'Won' || Op.StageName=='Won - Future Activation Date' ) && ResultR == True)){
                    Account tmpAccountR  = ACCTMAP.get(Op.AccountID);
                    tmpAccountR.Fit_Finder_Status__c = 'Active';
                    tmpAccountR.Fit_Finder_Program__c='Right Track';
                  AcctSet.add(tmpAccountR);
                
                    }
                  else{if((Op.StageName== 'Won' || Op.StageName=='Won - Future Activation Date' ) && (ResultR == True && Result == True) ){
                     Account tmpAccountRF= ACCTMAP.get(Op.AccountID);
                     tmpAccountRF.Fit_Finder_Status__c = 'Active';
                     tmpAccountRF.Fit_Finder_Program__c='Right Track';
                    AcctSet.add(tmpAccountRF);
                    
                    }
                  }
                }
            updACCT.addall(AcctSet);  
            }
          }
        }
    
   try{
        update updACCT;   <<-------- Same Place ,same error.
    }catch(DMLException d){
        system.debug('\n\nERROR UPDATING ACCOUNTS: '+d.getDMLMessage(0));
    }
}

JimRaeJimRae

I think I see what the issue is.  You need to move the updACCT.addall(AcctSet); outside of the for loop that is processing the opportunities.  Basically, put it on the line above the try{

 

That should eliminate your duplicates.

NightShadeNightShade

Jim,

 

I tried as below but I am getting same error at the same line no . Any more pointers, you could suggest  ? :)

 

Thanks 

 

 

trigger FFStatus on Opportunity (after update) {
  String f ='FF';
  String r='RT';
    Set<ID> OppIDs = new Set<ID>();
    Set<ID> AcctIDs = new Set<ID>();
    for(Opportunity o:Trigger.New){
        OppIDs.add(o.id);
        AcctIDs.add(o.accountid);
    }
    Map<ID,Account> ACCTMAP = new Map<ID,Account>([select id,Fit_Finder_Status__c from Account where id in:AcctIDs]);  //create a map list of accounts with the Account ID as the key
    
    
    List<Account> updACCT = new List<Account>(); //accounts in this list will get updated
    Set<Account> AcctSet = new Set<Account>();
   Map <ID,List<OpportunityLineItem>> OLIOPPMAP  = new Map <ID,List<OpportunityLineItem>> (); //create a map list of OLI with the Opportunity ID as the key, note that each opp could have more than one OLI
    for(OpportunityLineItem oli: [Select o.PricebookEntryId ,o.PricebookEntry.ProductCode,OpportunityID from OpportunityLineItem o where o.OpportunityId in :Trigger.New ]){
        if(OLIOPPMAP.containsKey(oli.OpportunityID)){
            OLIOPPMAP.get(oli.OpportunityID).add(oli);
        }else{
            OLIOPPMAP.put(oli.OpportunityID,new List<OpportunityLineItem>{oli});
        }
    }
     for (Opportunity Op :Trigger.new){
 
       if(OLIOPPMAP.containsKey(Op.id)){
            for (  OpportunityLineItem oli : OLIOPPMAP.get(Op.id) ){
                String pc;
                if(oli.PricebookEntry.ProductCode<>null){
                     pc = oli.PricebookEntry.ProductCode;
                }else{
                     pc ='';
                }
                Boolean Result = pc.Contains(f);   
                Boolean ResultR = pc.Contains(r);   
               
                if ( (Op.StageName== 'Won' || Op.StageName=='Won - Future Activation Date' ) && Result == True ){
                    Account tmpAccount = ACCTMAP.get(Op.AccountID);
                    tmpAccount.Fit_Finder_Status__c = 'Active';
                    tmpAccount.Fit_Finder_Program__c='Paying - Reg Customer';
                    AcctSet.add(tmpAccount);
                   
                } else{if ( ((Op.StageName== 'Won' || Op.StageName=='Won - Future Activation Date' ) && ResultR == True)){
                    Account tmpAccountR  = ACCTMAP.get(Op.AccountID);
                    tmpAccountR.Fit_Finder_Status__c = 'Active';
                    tmpAccountR.Fit_Finder_Program__c='Right Track';
                  AcctSet.add(tmpAccountR);
                
                    }
                  else{if((Op.StageName== 'Won' || Op.StageName=='Won - Future Activation Date' ) && (ResultR == True && Result == True) ){
                     Account tmpAccountRF= ACCTMAP.get(Op.AccountID);
                     tmpAccountRF.Fit_Finder_Status__c = 'Active';
                     tmpAccountRF.Fit_Finder_Program__c='Right Track';
                    AcctSet.add(tmpAccountRF);
                    
                    }
                  }
                }
           
            }
          }
        }
     updACCT.addall(AcctSet);
   try{
        update updACCT;
    }catch(DMLException d){
        system.debug('\n\nERROR UPDATING ACCOUNTS: '+d.getDMLMessage(0));
    }
}

JimRaeJimRae

That doesn't make any sense to me. It shouldn't be possible to get that error.

 

What I would typically do next is use debug statements to look at the data to see if I  could find the issue.

You add the system.debug statements to your code, and then open the system log when you execute your test.

 

Here is some example of debug output you could use.  You might also want to code some debug "loops" to show the actual values in the AcctSET and UpdACCT to see where the duplicate might be coming from.

 

I am curious if you have considered in your design to write this trigger; What happens if there are 2 opportuntiies on the same account, one with the FF and one without? 

 

 

trigger FFStatus on Opportunity (after update) {
  String f ='FF';
  String r='RT';
    Set<ID> OppIDs = new Set<ID>();
    Set<ID> AcctIDs = new Set<ID>();
    for(Opportunity o:Trigger.New){
        OppIDs.add(o.id);
        AcctIDs.add(o.accountid);
    }
    Map<ID,Account> ACCTMAP = new Map<ID,Account>([select id,Fit_Finder_Status__c from Account where id in:AcctIDs]);  //create a map list of accounts with the Account ID as the key
	//Added these for debugging
	system.debug('\n\n');//puts a blank line in the debug output
	system.debug('\n\nGOT ' + OppIDs.size() + ' Unique Opportunities in this trigger.');
	system.debug('\n\nGOT ' + AcctIDs.size() + ' Unique Accounts in this trigger.');
	system.debug('\n\n');//puts a blank line in the debug output
	//end debug section 1
    
    List<Account> updACCT = new List<Account>(); //accounts in this list will get updated
    Set<Account> AcctSet = new Set<Account>();
   Map <ID,List<OpportunityLineItem>> OLIOPPMAP  = new Map <ID,List<OpportunityLineItem>> (); //create a map list of OLI with the Opportunity ID as the key, note that each opp could have more than one OLI
    for(OpportunityLineItem oli: [Select o.PricebookEntryId ,o.PricebookEntry.ProductCode,OpportunityID from OpportunityLineItem o where o.OpportunityId in :Trigger.New ]){
        if(OLIOPPMAP.containsKey(oli.OpportunityID)){
            OLIOPPMAP.get(oli.OpportunityID).add(oli);
        }else{
            OLIOPPMAP.put(oli.OpportunityID,new List<OpportunityLineItem>{oli});
        }
    }
     for (Opportunity Op :Trigger.new){
 
       if(OLIOPPMAP.containsKey(Op.id)){
            for (  OpportunityLineItem oli : OLIOPPMAP.get(Op.id) ){
                String pc;
                if(oli.PricebookEntry.ProductCode<>null){
                     pc = oli.PricebookEntry.ProductCode;
                }else{
                     pc ='';
                }
                Boolean Result = pc.Contains(f);   
                Boolean ResultR = pc.Contains(r);   
               
                if ( (Op.StageName== 'Won' || Op.StageName=='Won - Future Activation Date' ) && Result == True ){
                    Account tmpAccount = ACCTMAP.get(Op.AccountID);
                    tmpAccount.Fit_Finder_Status__c = 'Active';
                    tmpAccount.Fit_Finder_Program__c='Paying - Reg Customer';
                    AcctSet.add(tmpAccount);
                   
                } else{if ( ((Op.StageName== 'Won' || Op.StageName=='Won - Future Activation Date' ) && ResultR == True)){
                    Account tmpAccountR  = ACCTMAP.get(Op.AccountID);
                    tmpAccountR.Fit_Finder_Status__c = 'Active';
                    tmpAccountR.Fit_Finder_Program__c='Right Track';
                  AcctSet.add(tmpAccountR);
                
                    }
                  else{if((Op.StageName== 'Won' || Op.StageName=='Won - Future Activation Date' ) && (ResultR == True && Result == True) ){
                     Account tmpAccountRF= ACCTMAP.get(Op.AccountID);
                     tmpAccountRF.Fit_Finder_Status__c = 'Active';
                     tmpAccountRF.Fit_Finder_Program__c='Right Track';
                    AcctSet.add(tmpAccountRF);
                    
                    }
                  }
                }
           
            }
          }
        }
     //start Debug section 2
	 system.debug('\n\nAcctSet has '+AcctSet.size() +' records);
	 
	 //end Debug Section 2
	 updACCT.addall(AcctSet);
	 //start Debug section 3
	 system.debug('\n\nupdACCT has '+updACCT.size() +' records);
	 //updACCT should have the same number of items as AcctSET does
	 //end Debug Section 3
   try{
        update updACCT;
    }catch(DMLException d){
        system.debug('\n\nERROR UPDATING ACCOUNTS: '+d.getDMLMessage(0));
    }
}

 

 

NightShadeNightShade

Hi Jim ,

 

I am gonna try that out right now , but just to answer your question . If theAccount has even a single Opportunity with FF code the field is updated to active and Pay-Reg Customer and if the Account has FF frirst and then a RT opportunitiy is added the field is updated to active and Right Track  and vice versa.Also a single opportunity can have two Products RT and FF and a single product which is RTFF, for RT and RTFF it should update  to active and Right Track and for FF to active and Pay-Reg Customer and again same as above the order in which they come the updates are made .I just got this clarified with BA . Would this change the way we have written my trigger significantly ?

 

Thanks a lot and Best Regards .

NightShadeNightShade

Hi Jim, 

 

Sorry to keep bothering you again and again . But I ran the code which u gave me and checked the debug and system logs and below is what I got from the debug log. I also changed my if else construct syntactically but I am still getting the same error. I reposting the code below if you could help me I woild be really greateful

 

Thanks and Regards

 

13:52:31.003|CODE_UNIT_STARTED|[EXTERNAL]|01qP0000000030o|FFStatus on Opportunity trigger event AfterUpdate for [006P0000002OUsA]
13:52:31.004|METHOD_ENTRY|[7]|SET.add(ANY)
13:52:31.004|METHOD_EXIT|[7]|SET.add(ANY)
13:52:31.004|METHOD_ENTRY|[8]|SET.add(ANY)
13:52:31.004|METHOD_EXIT|[8]|SET.add(ANY)
13:52:31.004|SOQL_EXECUTE_BEGIN|[10]|Aggregations:0|select id,Fit_Finder_Status__c from Account where id in:AcctIDs
13:52:31.020|SOQL_EXECUTE_END|[10]|Rows:1
13:52:31.021|METHOD_ENTRY|[12]|System.debug(ANY)
13:52:31.021|USER_DEBUG|[12]|DEBUG|


13:52:31.021|METHOD_EXIT|[12]|System.debug(ANY)
13:52:31.021|METHOD_ENTRY|[13]|System.debug(ANY)
13:52:31.021|METHOD_ENTRY|[13]|SET.size()
13:52:31.021|METHOD_EXIT|[13]|SET.size()
13:52:31.021|USER_DEBUG|[13]|DEBUG|

GOT 1 Unique Opportunities in this trigger.
13:52:31.021|METHOD_EXIT|[13]|System.debug(ANY)
13:52:31.021|METHOD_ENTRY|[14]|System.debug(ANY)
13:52:31.021|METHOD_ENTRY|[14]|SET.size()
13:52:31.021|METHOD_EXIT|[14]|SET.size()
13:52:31.021|USER_DEBUG|[14]|DEBUG|

GOT 1 Unique Accounts in this trigger.
13:52:31.021|METHOD_EXIT|[14]|System.debug(ANY)
13:52:31.021|METHOD_ENTRY|[15]|System.debug(ANY)
13:52:31.021|USER_DEBUG|[15]|DEBUG|


13:52:31.021|METHOD_EXIT|[15]|System.debug(ANY)
13:52:31.021|SOQL_EXECUTE_BEGIN|[21]|Aggregations:0|Select o.PricebookEntryId ,o.PricebookEntry.ProductCode,OpportunityID from OpportunityLineItem o where o.OpportunityId in :Trigger.New
13:52:31.027|SOQL_EXECUTE_END|[21]|Rows:2
13:52:31.027|METHOD_ENTRY|[22]|MAP.containsKey(ANY)
13:52:31.027|METHOD_EXIT|[22]|MAP.containsKey(ANY)
13:52:31.027|METHOD_ENTRY|[25]|MAP.put(ANY, ANY)
13:52:31.027|METHOD_EXIT|[25]|MAP.put(ANY, ANY)
13:52:31.027|METHOD_ENTRY|[22]|MAP.containsKey(ANY)
13:52:31.027|METHOD_EXIT|[22]|MAP.containsKey(ANY)
13:52:31.027|METHOD_ENTRY|[23]|LIST.add(ANY)
13:52:31.027|METHOD_ENTRY|[23]|MAP.get(ANY)
13:52:31.027|METHOD_EXIT|[23]|MAP.get(ANY)
13:52:31.027|METHOD_EXIT|[23]|LIST.add(ANY)
13:52:31.027|METHOD_ENTRY|[30]|MAP.containsKey(ANY)
13:52:31.027|METHOD_EXIT|[30]|MAP.containsKey(ANY)
13:52:31.027|METHOD_ENTRY|[31]|MAP.get(ANY)
13:52:31.028|METHOD_EXIT|[31]|MAP.get(ANY)
13:52:31.028|METHOD_ENTRY|[38]|String.contains(String)
13:52:31.028|METHOD_EXIT|[38]|String.contains(String)
13:52:31.028|METHOD_ENTRY|[39]|String.contains(String)
13:52:31.028|METHOD_EXIT|[39]|String.contains(String)
13:52:31.028|METHOD_ENTRY|[49]|MAP.get(ANY)
13:52:31.028|METHOD_EXIT|[49]|MAP.get(ANY)
13:52:31.028|METHOD_ENTRY|[52]|SET.add(ANY)
13:52:31.028|METHOD_EXIT|[52]|SET.add(ANY)
13:52:31.028|METHOD_ENTRY|[53]|System.debug(ANY)
13:52:31.028|METHOD_ENTRY|[53]|SET.size()
13:52:31.028|METHOD_EXIT|[53]|SET.size()
13:52:31.028|USER_DEBUG|[53]|DEBUG|

AcctSet has1 records
13:52:31.028|METHOD_EXIT|[53]|System.debug(ANY)
13:52:31.028|METHOD_ENTRY|[38]|String.contains(String)
13:52:31.028|METHOD_EXIT|[38]|String.contains(String)
13:52:31.028|METHOD_ENTRY|[39]|String.contains(String)
13:52:31.028|METHOD_EXIT|[39]|String.contains(String)
13:52:31.029|METHOD_ENTRY|[42]|MAP.get(ANY)
13:52:31.029|METHOD_EXIT|[42]|MAP.get(ANY)
13:52:31.029|METHOD_ENTRY|[45]|SET.add(ANY)
13:52:31.029|METHOD_EXIT|[45]|SET.add(ANY)
13:52:31.029|METHOD_ENTRY|[46]|System.debug(ANY)
13:52:31.029|METHOD_ENTRY|[46]|SET.size()
13:52:31.029|METHOD_EXIT|[46]|SET.size()
13:52:31.029|USER_DEBUG|[46]|DEBUG|

AcctSet has2 records
13:52:31.029|METHOD_EXIT|[46]|System.debug(ANY)
13:52:31.029|METHOD_ENTRY|[70]|System.debug(ANY)
13:52:31.029|METHOD_ENTRY|[70]|SET.size()
13:52:31.029|METHOD_EXIT|[70]|SET.size()
13:52:31.029|USER_DEBUG|[70]|DEBUG|

AcctSet has2 records
13:52:31.029|METHOD_EXIT|[70]|System.debug(ANY)
13:52:31.029|METHOD_ENTRY|[74]|LIST.addAll(SET)
13:52:31.029|METHOD_EXIT|[74]|LIST.addAll(SET)
13:52:31.029|METHOD_ENTRY|[76]|System.debug(ANY)
13:52:31.029|METHOD_ENTRY|[76]|LIST.size()
13:52:31.029|METHOD_EXIT|[76]|LIST.size()
13:52:31.029|USER_DEBUG|[76]|DEBUG|

updACCT has 2 records
13:52:31.029|METHOD_EXIT|[76]|System.debug(ANY)
13:52:31.029|DML_BEGIN|[80]|Op:Update|Type:Account|Rows:2
13:52:31.030|EXCEPTION_THROWN|[80]|System.ListException: Duplicate id in list: 001P000000FEbeqIAD
13:52:31.032|FATAL_ERROR|System.ListException: Duplicate id in list: 001P000000FEbeqIAD

 

 

 

My code :- It seems at the end of the third loop it is adding the same account again .

 

 

 

trigger FFStatus on Opportunity (after update) {
  String f ='FF';
  String r='RT';
    Set<ID> OppIDs = new Set<ID>();
    Set<ID> AcctIDs = new Set<ID>();
    for(Opportunity o:Trigger.New){
        OppIDs.add(o.id);
        AcctIDs.add(o.accountid);
    }
    Map<ID,Account> ACCTMAP = new Map<ID,Account>([select id,Fit_Finder_Status__c from Account where id in:AcctIDs]);  //create a map list of accounts with the Account ID as the key
    //Added these for debugging
    system.debug('\n\n');//puts a blank line in the debug output
    system.debug('\n\nGOT ' + OppIDs.size() + ' Unique Opportunities in this trigger.');
    system.debug('\n\nGOT ' + AcctIDs.size() + ' Unique Accounts in this trigger.');
    system.debug('\n\n');//puts a blank line in the debug output
    //end debug section 1
    
    List<Account> updACCT = new List<Account>(); //accounts in this list will get updated
    Set<Account> AcctSet = new Set<Account>();
   Map <ID,List<OpportunityLineItem>> OLIOPPMAP  = new Map <ID,List<OpportunityLineItem>> (); //create a map list of OLI with the Opportunity ID as the key, note that each opp could have more than one OLI
    for(OpportunityLineItem oli: [Select o.PricebookEntryId ,o.PricebookEntry.ProductCode,OpportunityID from OpportunityLineItem o where o.OpportunityId in :Trigger.New ]){
        if(OLIOPPMAP.containsKey(oli.OpportunityID)){
            OLIOPPMAP.get(oli.OpportunityID).add(oli);
        }else{
            OLIOPPMAP.put(oli.OpportunityID,new List<OpportunityLineItem>{oli});
        }
    }
     for (Opportunity Op :Trigger.new){
 
       if(OLIOPPMAP.containsKey(Op.id)){
            for (  OpportunityLineItem oli : OLIOPPMAP.get(Op.id) ){
                String pc;
                if(oli.PricebookEntry.ProductCode<>null){
                     pc = oli.PricebookEntry.ProductCode;
                }else{
                     pc ='';
                }
                Boolean Result = pc.Contains(f);   
                Boolean ResultR = pc.Contains(r);   
               
                if ( (Op.StageName== 'Won' || Op.StageName=='Won - Future Activation Date' ) && Result == True ){
                    Account tmpAccount = ACCTMAP.get(Op.AccountID);
                    tmpAccount.Fit_Finder_Status__c = 'Active';
                    tmpAccount.Fit_Finder_Program__c='Paying - Reg Customer';
                    AcctSet.add(tmpAccount);
                   system.debug('\n\nAcctSet has'   +AcctSet.size() + ' records');
                }
                 else if ( ((Op.StageName== 'Won' || Op.StageName=='Won - Future Activation Date' ) && ResultR == True)){
                    Account tmpAccountR  = ACCTMAP.get(Op.AccountID);
                    tmpAccountR.Fit_Finder_Status__c = 'Active';
                    tmpAccountR.Fit_Finder_Program__c='Right Track';
                  AcctSet.add(tmpAccountR);
                system.debug('\n\nAcctSet has'   +AcctSet.size() + ' records');
                    }
                  else if((Op.StageName== 'Won' || Op.StageName=='Won - Future Activation Date' ) && (ResultR == True && Result == True) ){
                     Account tmpAccountRF= ACCTMAP.get(Op.AccountID);
                     tmpAccountRF.Fit_Finder_Status__c = 'Active';
                     tmpAccountRF.Fit_Finder_Program__c='Right Track';
                    AcctSet.add(tmpAccountRF);
                    system.debug('\n\nAcctSet has'   +AcctSet.size() + ' records');
                    }
                  
                
           
            }
          }
        }
     //start Debug section 2
      
       system.debug('\n\nAcctSet has'   +AcctSet.size() + ' records');
     
     // end Debug Section 2
     
     updACCT.addall(AcctSet);
     //start Debug section 3
     system.debug('\n\nupdACCT has ' +updACCT.size() +  ' records');
     //updACCT should have the same number of items as AcctSET does
     //end Debug Section 3
   try{
        update updACCT;
    }catch(DMLException d){
        system.debug('\n\nERROR UPDATING ACCOUNTS:  '+d.getDMLMessage(0));
    }
}

 

 

 

 

 

 

 

 

 

 

 

 

JimRaeJimRae

The only thing I can see is the Set is getting 2 accounts added to it, it must not think they are equivelant because they are coming from the map.

What you will need to do is refactor your if logic so that you only add an account to the list once, or some code to take the resulting list from your if statements and make sure there is only one unique entry for each account.

Sorry I can't offer more, but I am tied up on a project myself.

NightShadeNightShade

Hi Jim ,

 

Thanks a lot for all your help .

 

 

Thanks and Regards