+ Start a Discussion
NightShadeNightShade 

Help with Trigger

Hi everyone,

 

 

I have a trigger below for which I got help from the discussion board itself but i have not been able to completely resolve it . Below is my Scenario , error and my Trigger code . If  someone could help me please resolve this I would be grateful.

 

Thanks and Regards

 

 

Scenario :

Opportunity Line Items have Products with Product Codes which contain the Strings : FF , RT and (RT and FF). I need to update the account fields “Fit Finder Status “ and “Fit Finder Program “ related to the Opportunity which has products with these product Codes. For an Opportunity with FF string in the product code the  Fit Finder Status  is updated to  ‘Active’ and Fit Finder Program  to ‘Paying-Reg Customer’ .If another product with RT or (RT and FF) is added under the same opportunity the Fit Finder Status  is updated to  ‘Active’ and Fit Finder Program  to ‘Right Track’.

 

 

 

Error : 

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

The above Id is an Account ID .

 

Trigger Code :

 

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;    <<----- This the line 80 where the error refers to.

    }catch(DMLException d){

        system.debug('\n\nERROR UPDATING ACCOUNTS:  '+d.getDMLMessage(0));

    }

}

 

 

 

 

 

 

cloudcodercloudcoder

Without reading through all the code, a duplicate id in your list is likely indicative of an error in the logic. You have a few options, in order of preference.

 

1. use a Set instead of a LIst. Sets do not allow duplicates and you can add a check list if(mySet.contains('blah')) before adding another id

 

2. Change the way you insert your collection to use the Database.insert(..) method and handle the SaveResults appropriately esp if you did not intend to add duplicates (see #1)

 

I would definitely look at option #1 if I were you

ericszulcericszulc

Well... I haven't completely read through all the code, but the error says you have duplicate account ids in the list you are updating. I'm not completely familiar with Sets of sObjects (haven't tested thoroughly), but from this page, my guess is that uniqueness in sObjects is kind of tricky to get.

 

http://www.salesforce.com/us/developer/docs/apexcode/Content/langCon_apex_collections_sets.htm 

 

 

One way I can think to get around this is to use Map<Id, Account> acct_map for saving accounts you want to update. Then turn the map into a list as such List<account> updateAcct_list = acct_map.values(); That way you know that no duplicate ids will exist.

 

Hope that helps.