+ Start a Discussion
Shawn Reichner 29Shawn Reichner 29 

Trigger/Trigger Handler More than 1 row assigned error: Please Help!

Hello awesome Developers! 

I have the following Trigger and then Trigger Handler to pass of the processing work to the class for more efficiency than multiple triggers per object.  Now on single record inserts, updates or deletes the code works just fine and as designed.  When I use Data Loader to attempt to Bulk test more than a single record I get the following error. 

System.QueryException: List has more than 1 row for assignment to SObject
The logs show it starts from line 58 on the Trigger and calls a specific Method in the class. 

I have tested and all methods give this same error but wanted to provide as many details in order to get some great help on this one.  Can you help, and save the day!  It woudl greatly be appreciated.  

I added tons of comments to help walk through the process of what is needed, thank you so much in advance for any suggestions and or insight you may be able to give this beginner'ish developer.

Here is my trigger code:
 
trigger ContactTriggerMaster on Contact (after insert, after update, after delete, after undelete) {

    //Begin Insert Processing
    if(trigger.isAfter){
        
    	if(trigger.isInsert && !trigger.IsUpdate){
            
       		ContactHandlerMaster.afterInsert(trigger.new);
            
        //End of Insert Processing
        //Start of Update Processing
    	}else if(trigger.isUpdate && !trigger.isInsert){
            
            //Create Lists, Maps and Variables
            //List(new) and Map(old) of Contacts for Person Score Code
            List<Contact> newcons = new List<Contact>();
            Map<ID,Contact> oldCons = new Map<ID,Contact>();
            
            //List(new) and Map(old) of Contacts for Stage Progression Code 
            List<Contact> newConsStage = new List<Contact>();
            Map<ID,Contact> oldConsStage = new Map<ID,Contact>();
            
            //List(new) and Map(old) of Contacts for Meeting Set Code
           // List<Contact> newMeetDate = new List<Contact>();
           // Map<ID,Contact> oldMeetDate = new Map<ID,Contact>();
            
            //List(new) and Map(old) of Contacts for Meeting Kept Code
            //List<Contact> newMeetSet = new List<Contact>();
           // Map<ID,Contact> oldMeetSet = new Map<ID,Contact>();
            
            //Iterate over incoming Trigger Records
            for(integer i=0;i<trigger.new.size();i++){
                
                //If Person Score Has Changed on Contact add Trigger.new to List and Trigger.oldMap to Map
                if(trigger.new[i].Person_Score__c != trigger.old[i].Person_Score__c){
              		newCons.addAll(trigger.new);
                    oldCons.putAll(trigger.old);
                    
				//If Contract Stage Has Changed on Contact add Trigger.new to List and Trigger.oldMap to Map
                }else if(trigger.new[i].Contact_Status__c != trigger.old[i].Contact_Status__c){
                    newConsStage.addAll(trigger.new);
                    oldConsStage.putAll(trigger.old);
                
                //If Meeting Chedule For Date Has Changed on Contact add Trigger.new to List and Trigger.oldMap to Map
                }//else if(trigger.new[i].Meeting_Scheduled_For__c != trigger.old[i].Meeting_Scheduled_For__c){
                  //  newMeetDate.addAll(trigger.new);
                  //  oldMeetDate.putAll(trigger.old);
                    
                //If Meeting Kept Checkbox Has Changed on Contact add Trigger.new to List and Trigger.oldMap to Map
               // }else if(trigger.new[i].Meeting_Kept__c != trigger.old[i].Meeting_Kept__c){
               //     newMeetSet.addAll(trigger.new);
               //     oldMeetSet.putAll(trigger.old);
              //  }
            }
            
            //Do null checks of List and Map and then Pass the non null List and Map to Handler Class
            if(newCons!=null || oldCons!=null){
                ContactHandlerMaster.afterPersonUpdate(newCons, oldCons);
            }
            if(newConsStage!=null || oldConsStage!=null){
                ContactHandlerMaster.afterStageUpdate(newConsStage, oldConsStage);
            }
          //  if(newMeetDate!=null || oldMeetDate!=null){
           //     ContactHandlerMaster.afterMeetingUpdate(newMeetDate, oldMeetDate);
           // }
           // If(newMeetSet !=null || oldMeetSet!=null){
           //     ContactHandlerMaster.afterMeetingUpdate(newMeetSet, oldMeetSet);
           // }//End of Update Processing
            
         // Begin Delete Processing
    	}else if(trigger.isDelete){
       		ContactHandlerMaster.afterDelete(trigger.oldMap);
    	}
            
    }else if(trigger.isBefore){
        
    }
    
}

And here is my Trigger Handler Class Code:
 
public class ContactHandlerMaster {

    public static void afterInsert(List<Contact> newRecords){
     	//Start Insert Code
     	
     	//Create Set to hold Acct Ids to process
        Set<ID> acctIds = new Set<ID>();
        //Null Check for incoming list
        if(newRecords!=null){
        //Loop through the incoming list of Contacts
        for(Contact cons : newRecords){
            //Add Acct Ids to acctIds set
            acctIds.add(cons.AccountId);
        }//End of FOR Loop
        }//End of Null Check
        //Create Maps to hold Contacts and Accounts to use for Rollup of Person Score
        Map<ID, Contact> contactsForAccounts = new Map<ID, Contact>([SELECT Id ,AccountId, 
                                                                     Person_Score__c FROM Contact 
                                                                     WHERE AccountId IN :acctIds FOR UPDATE]);
		Map<ID, Account> acctsToUpdate = new Map<ID, Account>([SELECT Id, Account_Score__c 
                                                               FROM Account WHERE Id IN :acctIds FOR UPDATE]);
        //Loop through the Contact Children of the Accounts in acctsToUpdate Map to SUM all Person Scores into totalValue variable
        for (Account acct : acctsToUpdate.values()) {
			Decimal totalValue = 0;
				for (Contact con : contactsForAccounts.values()) {
    				if (con.AccountId == acct.Id && con.Person_Score__c != NULL) {
        				totalValue += con.Person_Score__c; 
    				}
				}//End of For Loop
        //Set the Account Score to use the value of the SUMMED Person Score in TotalValue Variable
		acct.Account_Score__c = totalValue;
		}
        //Null Check for Update DML
		if(acctsToUpdate.values().size() > 0) {
    		update acctsToUpdate.values();
		}
    }
    
    //Start Update Method
    public static void afterPersonUpdate(List<Contact> newRecords,Map<ID,Contact> oldMap){
        
        //Start Variable Collection to use for Update Methods defined below
        //List of Contacts with new version of records
        List<Contact> consRcv = newRecords;
        system.debug('consRcv Size is - '+consRcv.size()+'IDs are - '+consRcv);
        //Initite List and Map to hold new and old values of the incoming records
        List<Contact> newRecordsUpdate = new List<Contact>();
        Map<ID,Contact> oldMapUpdate = new Map<ID,Contact>();
        //Initiate Decimal variables to hold new and old Person Score Data
        Decimal NewScore;
        Decimal OldScore;
        //Null check on consRvc List
        if(consRcv!=null){ 
            system.debug('newConRecord List Size Is - '+newRecords.size());
        //Loop through the consRcv List
        for(Contact c : consRcv){
              //Add new version of record to List newRecordsUpdate
              newRecordsUpdate.add(c);
            system.debug('newConRecordsUpdate Size After ran through For Loop is - '+newRecordsUpdate.size());
              //Make NewScore variable the value of the Person Score of the incoming record
              NewScore = c.Person_Score__c;
            system.debug('NewScore is - '+NewScore);
            }
        }
        system.debug('Con Record Update List Size is - '+newRecordsUpdate.size());
        //Null check on oldMap Map
        if(oldMap.Values()!=null){
            system.debug('ConoldMap Size is - '+oldMap.Size());
        //Loop through oldMap values and add to oldMapUpdate Map as set oldScore variable to old Person Score version
        for(Contact cold : oldMap.Values()){
              oldMapUpdate.put(cold.Id,OldMap.Values());
              OldScore = cold.Person_Score__c;
        }
        }
        system.debug('ConoldMapUpdate Size is - '+oldMapUpdate.size());
        
        //Enter into Update Person Score Rollup Code
        //Checking to ensure old person score and new person score has changed
        if(NewScore != OldScore){
        //Create Set to hold Acct Ids to Process
        Set<ID> acctIds = new Set<ID>();
        //Null check on consRcv List
        if(consRcv!=null){
        //Loop through consRcv List and add Acct Ids to acctIds Set for processing
        for(Contact cons : consRcv){
            acctIds.add(cons.AccountId);
        }
        }
        //Create Maps to hold Conacts and Accounts for processing
        Map<ID, Contact> contactsForAccounts = new Map<ID, Contact>([SELECT Id ,AccountId, 
                                                                     Person_Score__c FROM Contact 
                                                                     WHERE AccountId IN :acctIds FOR UPDATE]);
		Map<ID, Account> acctsToUpdate = new Map<ID, Account>([SELECT Id, Account_Score__c 
                                                               FROM Account WHERE Id IN :acctIds FOR UPDATE]);
            
        //Loop through the Contact Children of the Accounts in acctsToUpdate Map to SUM all Person Scores into totalValue variable
        for (Account acct : acctsToUpdate.values()) {
			Decimal totalValue = 0;
				for (Contact con : contactsForAccounts.values()) {
    				if (con.AccountId == acct.Id && con.Person_Score__c != NULL) {
        				totalValue += con.Person_Score__c; 
    				}
				}
        //Make account score the value of thr SUMMED totalValue variable
		acct.Account_Score__c = totalValue;
		}
        //Null check on acctsToUpdate Map before attempt to update Map
		if(acctsToUpdate.values().size() > 0) {
    		update acctsToUpdate.values();
		}
        } // End of Person Score Rollup Code
    }//End of afterPersonUpdate Method
    
       //Begin Stage Progression Code
       public static void afterStageUpdate(List<Contact> newRecords,Map<ID,Contact> oldMap){
        
        //Create Lists and Variables to use for processing
        //List to Hold New Version of incoming Contacts to process
        List<Contact> consRcv = newRecords;
        system.debug('consRcv Size is - '+consRcv.size()+'IDs are - '+consRcv);
        //List and Map to hold post looped records for processing
        List<Contact> newRecordsUpdate = new List<Contact>();
        Map<ID,Contact> oldMapUpdate = new Map<ID,Contact>();
        //String Variables to hold old and new Contact Stage Values
        String NewStage;
        String OldStage;
        
        //Null check on consRcv List  
        if(consRcv!=null){ 
            system.debug('newConRecord List Size Is - '+newRecords.size());
        //Loop through consRcv List and add records to newRecordsUpdate List
        for(Contact c : consRcv){
              newRecordsUpdate.add(c);
            system.debug('newConRecordsUpdate Size After ran through For Loop is - '+newRecordsUpdate.size());
              //Set NewStage variable to the New version of the Contact Stage value
              NewStage = c.Contact_Status__c;
            system.debug('NewStage is - '+NewStage);
            }//End of For Loop
        }//End of Null Check
        system.debug('Con Record Update List Size is - '+newRecordsUpdate.size());
        
        //Null check on oldMap
        if(oldMap.Values()!=null){
            system.debug('ConoldMap Size is - '+oldMap.Size());
        //Loop through oldMap Values to add records to oldMapUpdate Map
        for(Contact cold : oldMap.Values()){
              oldMapUpdate.put(cold.Id,OldMap.Values());
              //Set OldStage to the old version of the Contact Stage value
              OldStage = cold.Contact_Status__c;
        }
        }
        system.debug('ConoldMapUpdate Size is - '+oldMapUpdate.size()); 
        //Start of Contact Stage Progression Code
        //If NewStage value does not equal to OldStage value and update happened and should continue process
        if(NewStage != OldStage){
            //Create list to hold acct Ids for processing
            List<Account> accts = new List<Account>();
            //Null check on newRecords List of incoming records
        	if(newRecords!=null){
                //Loop through newContact Incoming List and perfrom logic
        		for(Contact cons : newRecords){
                    //Contact Stage Equals Assigned Logic
                    if(cons.Contact_Status__c == 'Assigned' && cons.Account_Stage__c == 'Ready'){
                        //If True create List of Accounts that belong to Contact being processed
                    	List<Account> accounts = [SELECT ID,Account_Stage__c FROM Account WHERE ID =: cons.AccountId FOR UPDATE];
                        //Loop through list of Accounts captured and set Account Stage to Assigned and add to accts List
                        for(Account a : accounts){
                    	a.Account_Stage__c = 'Assigned';
                        accts.add(a);
                        }//Contact Stage Equals Working Logic
                    }else if(cons.Contact_Status__c == 'Working' &&
                            (cons.Account_Stage__c == 'Ready' || cons.Account_Stage__c == 'Assigned')){
                                //If True create List of Accounts that belong to Contact being processed
                                List<Account> accounts = [SELECT ID,Account_Stage__c FROM Account WHERE ID =: cons.AccountId FOR UPDATE];
                                //Loop through list of Accounts captured and set Account Stage to Working and add to accts List
                                for(Account a : accounts){
                    			a.Account_Stage__c = 'Working';
            					accts.add(a);
                                }//Contact Stage Equal to Follow Up Logic
                    }else if(cons.Contact_Status__c == 'Follow-Up' &&
                            (cons.Account_Stage__c == 'Ready' || cons.Account_Stage__c == 'Assigned' || cons.Account_Stage__c == 'Working')){
                                //If true create List of Accounts that belong to Contact being processed
                                List<Account> accounts = [SELECT ID,Account_Stage__c FROM Account WHERE ID =: cons.AccountId FOR UPDATE];
                                //Loop through list of Accounts captured and set Account Stage to Follow Up and add to accts List
                                for(Account a : accounts){
                    			a.Account_Stage__c = 'Follow Up';
            					accts.add(a);
                                }//Contact Stage Equal to Active Opportunity Logic
                    }else if(cons.Contact_Status__c == 'Active Opportunity' &&
                            (cons.Account_Stage__c == 'Ready' || cons.Account_Stage__c == 'Assigned' || 
                             cons.Account_Stage__c == 'Working' || cons.Account_Stage__c == 'Follow Up')){
                                //If true create List of Accounts that belong to Contact being processed
                                List<Account> accounts = [SELECT ID,Account_Stage__c FROM Account WHERE ID =: cons.AccountId FOR UPDATE];
                                 //Loop through list of Accounts captured and set Account Stage to Active Opportunity and add to accts List
                                 for(Account a : accounts){
                    			a.Account_Stage__c = 'Active Opportunity';
            					accts.add(a);
                                 }//Contact Stage Equal to Closed Won Logic
                    }else if(cons.Contact_Status__c == 'Closed Won' &&
                            (cons.Account_Stage__c == 'Ready' || cons.Account_Stage__c == 'Assigned' || 
                             cons.Account_Stage__c == 'Working' || cons.Account_Stage__c == 'Follow Up' ||
                             cons.Account_Stage__c == 'Active Opportunity')){
                                //If true create List of Accounts that belong to Contact being processed
                                List<Account> accounts = [SELECT ID,Account_Stage__c FROM Account WHERE ID =: cons.AccountId FOR UPDATE];
                                //Loop through list of Accounts captured and set Account Stage to Closed Won and add to accts List
                                for(Account a : accounts){
                    			a.Account_Stage__c = 'Closed Won';
            					accts.add(a);
                                }
                    }
        		}
        	}//Null check on accts List size and Do Update DML
            if(accts.size()>0){
           		update accts; 
            }
        }
    }//End of afterStageUpdate Method
    
    //Begin Meeting Scheduled For Date Being Changed Method
    /*public static void afterMeetingUpdate(List<Contact> newRecords,Map<ID,Contact> oldMap){
        
        //Create Variables to use for Processing
        //List of incoming Contacts in thier new version
        List<Contact> consRcvMeet = newRecords;
        system.debug('consRcvMeet Size is - '+consRcvMeet.size()+'IDs are - '+consRcvMeet);
        //Create List and Map to hold new version and old version of incoming records
        List<Contact> newRecordsUpdate = new List<Contact>();
        Map<ID,Contact> oldMapUpdate = new Map<ID,Contact>();
        //create variables to hold old and new versions of the Meeting Scheduled For field
        Date NewMeeting;
        Date OldMeeting;
        //create variables to hold old and new versions of the Meeting Kept Field
        Boolean NewSet;
        Boolean OldSet;
        
        //Null Check on consRcvMeet List of incoming records
        if(consRcvMeet!=null){ 
            system.debug('newConRecord List Size Is - '+newRecords.size());
        //Loop though consRcvMeet records and add to newRecordsUpdate List
        for(Contact c : consRcvMeet){
              newRecordsUpdate.add(c);
            system.debug('newConRecordsUpdate Size After ran through For Loop is - '+newRecordsUpdate.size());
              //Set NewMeeting and NewSet variables to the new versions of both
              NewMeeting = c.Meeting_Scheduled_For__c;
              NewSet = c.Meeting_Kept__c;
            system.debug('NewMeeting is - '+NewMeeting);
            }//End of For Loop
        }//End of Null Check
        system.debug('Con Record Update List Size is - '+newRecordsUpdate.size());
        
        //Null check on oldMap of old versions of incoming records
        if(oldMap.Values()!=null){
            system.debug('ConoldMap Size is - '+oldMap.Size());
        //Loop through oldMap Values to insert old version of incoming records into the oldMapUpdate Map for processing
        for(Contact cold : oldMap.Values()){
              oldMapUpdate.put(cold.Id,OldMap.Values());
              //Set OldMeeting and OldMap variables to the old versions of Meeting Scheduled For and Meetign Kept values
              OldMeeting = cold.Meeting_Scheduled_For__c;
              OldSet = cold.Meeting_Kept__c;
        }
        }
        system.debug('ConoldMapUpdate Size is - '+oldMapUpdate.size());
        
        //Check to verify new Meeting Scheduled For value is different than Old Meeting Scheduled For Value
        if(NewMeeting != OldMeeting){
            //If true create list to hold accounts to process
            List<Account> accts = new List<Account>();
            //Loop through the incoming Contact Records
            for(Contact conMeetDate : newRecords){
                Account meetDateUpdate = [SELECT ID,Meeting_Scheduled_For__c FROM Account WHERE ID =: conMeetDate.AccountId FOR UPDATE];
                meetDateUpdate.Meeting_Scheduled_For__c = conMeetDate.Meeting_Scheduled_For__c;
                accts.add(meetDateUpdate);    
            }//Update accts and perform DML
            update accts;
            //Can Now Process if Meeting Kept checkbox has changed
        }else if(NewSet != OldSet){
          //If true create List to hold Acct Ids for processing
          List<Account> accts = new List<Account>();
            //Loop through incoming Contacts to update Account and add to acct List
            for(Contact conMeetDate : newRecords){
                Account meetDateUpdate = [SELECT ID,Meeting_Kept__c FROM Account WHERE ID =: conMeetDate.AccountId FOR UPDATE];
                meetDateUpdate.Meeting_Kept__c = conMeetDate.Meeting_Kept__c;
                accts.add(meetDateUpdate);
                }//End of For Loop
            //Update accts List and perform DML
            update accts;
        }
        }*/ //ENd of Meeting Code 
 		 // End of Update Meeting Method
    
    public static void afterDelete(Map<ID,Contact> oldMap){
        //Start After Delete Code
        //Start Person Score Rollup Subtract Code
        //Create a Set to hold Acct Ids to process
        Set<ID> acctIds = new Set<ID>();
        //Null check on oldMap version of deleted record
        if(oldMap!=null){
        //Loop through incoming deleted contacts and add thier acct Ids to acctIds set
        for(Contact cons : oldMap.Values()){
            acctIds.add(cons.AccountId);
        }
        }
        //Create Maps to hold Contact and Account records for processing 
        Map<ID, Contact> contactsForAccounts = new Map<ID, Contact>([SELECT Id ,AccountId, 
                                                                     Person_Score__c FROM Contact 
                                                                     WHERE AccountId IN :acctIds FOR UPDATE]);
		Map<ID, Account> acctsToUpdate = new Map<ID, Account>([SELECT Id, Account_Score__c 
                                                               FROM Account WHERE Id IN :acctIds FOR UPDATE]);
        //Loop through Accts to update Map and then Contacts for Accounts Map to SUM Cons Person Score
        for (Account acct : acctsToUpdate.values()) {
			Decimal totalValue = 0;
				for (Contact con : contactsForAccounts.values()) {
    				if (con.AccountId == acct.Id && con.Person_Score__c != NULL) {
        				totalValue += con.Person_Score__c; 
    				}//End of if logic
				}//End of For Loop
        //Update accts to now have SUMMED totalValue for Total Account Score
		acct.Account_Score__c = totalValue;
		}
        //Null check on acctsToUpdate Map and if not do DML
		if(acctsToUpdate.values().size() > 0) {
    		update acctsToUpdate.values();
		}
    }
    
}