+ Start a Discussion
StephenJacobGoldbergStephenJacobGoldberg 

System.FinalException: Record is read-only: Class.CommissionHelper.updateCommission

I have a trigger which calls a method in an apex class to update an object.  I am getting the error "execution of AfterUpdate caused by: System.FinalException: Record is read-only: Class.CommissionHelper.updateCommissions: line 49, column 6" and I am not sure why please help! 

 

Apex class

 

 

public static void updateCommissions(List<Commission__c> commList){
		List<Quote> quoteList = new List<Quote>();
		List<Commission__c> commUpdateList = new List<Commission__c>();
		Set<ID> qIds = new Set<ID>();
		for(Commission__c c: commList){
			qIds.add(c.Quote__c);
			
			
		}
		
		quoteList = [select Id, Sales_Commission__c FROM Quote where id in: qIds];
		
		for(Commission__c c: commList){
			for(Quote q: quoteList){
				if(q.id == c.Quote__c){
					c.Sales_Commission__c = q.Sales_Commission__c * c.Split_Percentage__c/100;
					commUpdateList.add(c);
				}
			}
		}
		
		update commUpdateList;
		
	}

 

 

Apex Trigger

 

 

 

trigger Commission_Before on Commission__c (after insert, after update) {
	
	Map <id, double> totalSplitMap = new Map<id, double>();
	totalSplitMap = CommissionHelper.caclulateTotalSplit(Trigger.new);
	system.debug('totalSplitMap: ' + totalSplitMap);
	
	for(Commission__c c: Trigger.new){
		system.debug('totalSplit: ' + totalSplitMap.get(c.id) );
		if(totalSplitMap.get(c.id) > 100){
			
			c.addError('The Total Commission across splits must equal 100. It is currently equal to ' + totalSplitMap.get(c.id));
			
			
		}
		else{
			
			CommissionHelper.updateCommissions(Trigger.new);
		}
		
	
		
		
		
	}
	
	 

	
}

 

 

Best Answer chosen by Admin (Salesforce Developers) 
StephenJacobGoldbergStephenJacobGoldberg

Ok now  I did really solve it myself ....  thought I did before but here it is for real.  I had to break it into two triggers a before and an after.  I throw the error in the after trigger, and do the update in the before trigger. That solves the problem. 

All Answers

uptime_andrewuptime_andrew

Is this your full code?  I don't see 49 lines here in this class.

 

My guess is that the running user can't make updates to Commission__c object.  Have you confirmed the profile in question has rights?

Commission__cComission__c object
sravusravu

Can you post your entire apex class.

And if I am not wrong, the issue might be with the relationship between the the commission object and the quote object.

What kind of relationship do you have between these two objects?

If it is a master-detail relationship then this might be causing the error.

If you can post the entire code and mention the relationship between the object it will be more easier to look into the error.

StephenJacobGoldbergStephenJacobGoldberg

Here is the full class   ... and yes it is a master detail relationship 

 

 

 

public with sharing class CommissionHelper {
	
	public List <Commission__c> commInsertList = new List<Commission__c>();
	public List <Quote> quoteList = new List<Quote>();
	
	

	
	
	public static void updateCommissions(List<Quote> qtList){
		List<Quote> qList = qtList;
		List <Commission__c> commList = new List <Commission__c>();
		List <Commission__c> commUpdateList = new List<Commission__c>();
		Set<ID> qIds = new Set<ID>();
		for(Quote q: qList){
			qIds.add(q.id);
			
		}
		commList = [select Id, Sales_Commission__c,Split_Percentage__c, Quote__c FROM Commission__c where Quote__c in: qIds];
		
		for(Quote q: qList){
			for(Commission__c c: commList){
				if(q.id == c.Quote__c){		
					c.Sales_Commission__c = q.Sales_Commission__c * c.Split_Percentage__c/100;
					system.debug('c.Sales_Commission__c: ' + c.Sales_Commission__c );
					commUpdateList.add(c);		
				}
			}
		}
		update commUpdateList;
		
		UserInfo.getName()
		
	}
	
	public static void updateCommissions(List<Commission__c> commList){
		List<Quote> quoteList = new List<Quote>();
		List<Commission__c> commUpdateList = new List<Commission__c>();
		Set<ID> qIds = new Set<ID>();
		for(Commission__c c: commList){
			qIds.add(c.Quote__c);
			
			
		}
		
		quoteList = [select Id, Sales_Commission__c FROM Quote where id in: qIds];
		
		for(Commission__c c: commList){
			for(Quote q: quoteList){
				if(q.id == c.Quote__c){
					c.Sales_Commission__c = q.Sales_Commission__c * c.Split_Percentage__c/100;
					commUpdateList.add(c);
				}
			}
		}
		
		update commUpdateList;
		
	}
	
	public  static Map<id, double> caclulateTotalSplit(List<Commission__c> commList){
		set<ID> qIds = new Set<ID>();
		Map<id, double> totalSplitMap = new Map<id, double>();
		for(Commission__c c: commList){
			qIds.add(c.Quote__c);
			
		}
		
		List <Commission__c> totalCommissionList = new List<Commission__c>();
		totalCommissionList = [select id, Quote__c, Split_Percentage__c FROM Commission__c WHERE Quote__c in: qIds];
		
		
		
		for(ID qid: qIds){
			Double totalSplit = 0; 
			List<Commission__c> thisQoutesComs = new List<Commission__c>();
			for(Commission__c c:totalCommissionList){
				if(qId == c.Quote__c){
					totalSplit = totalSplit + c.Split_Percentage__c;
					thisQoutesComs.add(c);
					
				}
			}	
			
			for(Commission__c c : thisQoutesComs){
				totalSplitMap.put(c.id, totalSplit);	
				
			}		
				
				
			
		}
		
		return totalSplitMap;
		
	}
	
	
	
	
	public static void insertCommissionsOnNewQuote(List<Quote> qtList){
		List<Quote> qList = qtList;
		List <Commission__c> commInsertList = new List<Commission__c>();
		
		for(Quote q: qList){
			
			Commission__c comm = new Commission__c(Name = 'Commission Split', Sales_Executive__c = q.CreatedById, Split_Percentage__c = 100, Quote__c = q.id,Sales_Commission__c = q.Sales_Commission__c ); 
			commInsertList.add(comm);
		}
		insert commInsertList;
			
		
	}
	

}

 

 

sravusravu

Ok one peroblem i can see is you have declared commList inside the method and you are trying to use the same in another method. Declare it as a public static variable (class variable) and see.

 

List <Commission__c> commList = new List <Commission__c>();

StephenJacobGoldbergStephenJacobGoldberg

updated the code... wasn't trying to use the same list as its not the same set of values so I declared the lists locally. This did not help. 

 

 

 

public with sharing class CommissionHelper {

	public static void updateCommissions(List<Quote> qtList){
		List<Quote> qList = qtList;
		List <Commission__c> commList = new List <Commission__c>();
		List <Commission__c> commUpdateList = new List<Commission__c>();
		Set<ID> qIds = new Set<ID>();
		for(Quote q: qList){
			qIds.add(q.id);
			
		}
		commList = [select Id, Sales_Commission__c,Split_Percentage__c, Quote__c FROM Commission__c where Quote__c in: qIds];
		
		for(Quote q: qList){
			for(Commission__c c: commList){
				if(q.id == c.Quote__c){		
					c.Sales_Commission__c = q.Sales_Commission__c * c.Split_Percentage__c/100;
					system.debug('c.Sales_Commission__c: ' + c.Sales_Commission__c );
					commUpdateList.add(c);		
				}
			}
		}
		update commUpdateList;
		
	}
	
	public static void updateCommissions(List<Commission__c> commList){
		List<Quote> quoteList = new List<Quote>();
		List<Commission__c> commsList = new List<Commission__c>(commList);
		List<Commission__c> commUpdateList = new List<Commission__c>();
		Set<ID> qIds = new Set<ID>();
		for(Commission__c c: commsList){
			qIds.add(c.Quote__c);
			
			
		}
		
		quoteList = [select Id, Sales_Commission__c FROM Quote where id in: qIds];
		
		for(Commission__c c: commsList){
			for(Quote q: quoteList){
				if(q.id == c.Quote__c){
					c.Sales_Commission__c = q.Sales_Commission__c * c.Split_Percentage__c/100;
					commUpdateList.add(c);
				}
			}
		}
		
		update commUpdateList;
		
	}
	
	public  static Map<id, double> caclulateTotalSplit(List<Commission__c> commList){
		List<Commission__c> commsList = new List<Commission__c>(commList);
		set<ID> qIds = new Set<ID>();
		Map<id, double> totalSplitMap = new Map<id, double>();
		for(Commission__c c: commsList){
			qIds.add(c.Quote__c);
			
		}
		
		List <Commission__c> totalCommissionList = new List<Commission__c>();
		totalCommissionList = [select id, Quote__c, Split_Percentage__c FROM Commission__c WHERE Quote__c in: qIds];
		
		
		
		for(ID qid: qIds){
			Double totalSplit = 0; 
			List<Commission__c> thisQoutesComs = new List<Commission__c>();
			for(Commission__c c:totalCommissionList){
				if(qId == c.Quote__c){
					totalSplit = totalSplit + c.Split_Percentage__c;
					thisQoutesComs.add(c);
					
				}
			}	
			
			for(Commission__c c : thisQoutesComs){
				totalSplitMap.put(c.id, totalSplit);	
				
			}		
				
				
			
		}
		
		return totalSplitMap;
		
	}
	
	
	
	
	public static void insertCommissionsOnNewQuote(List<Quote> qtList){
		List<Quote> qList = qtList;
		List <Commission__c> commInsertList = new List<Commission__c>();
		
		for(Quote q: qList){
			
			Commission__c comm = new Commission__c(Name = 'Commission Split', Sales_Executive__c = q.CreatedById, Split_Percentage__c = 100, Quote__c = q.id,Sales_Commission__c = q.Sales_Commission__c ); 
			commInsertList.add(comm);
		}
		insert commInsertList;
			
		
	}
	

}

 

 

sravusravu

When I tried to test your code in my instance it is giving me error in the trigger saying invalid method or signature

 

commissionhelper.updatecommissions(Trigger.new[0]);

 

It seems in the method you are using List<Quote> but in the trigger you are passing List<Commission__c>

 

and you have two methods with the same name in the class---little bit confusing to understand

 

StephenJacobGoldbergStephenJacobGoldberg

Thanks for your help sravu, thats not the issue though.  The issue is that it is an after update trigger rather than a before update.  This is causing some sort of problem with read-only and locking. 

 

Stephen 

StephenJacobGoldbergStephenJacobGoldberg

Ok now  I did really solve it myself ....  thought I did before but here it is for real.  I had to break it into two triggers a before and an after.  I throw the error in the after trigger, and do the update in the before trigger. That solves the problem. 

This was selected as the best answer
bujjibujji

Hi,

 

I have written a trigger on Oppurtunity but while saving the record i am getting the following error.

System.FinalException: Record is read-only

---------------------------------------------------------------------------------------------------

 

trigger oppInsrt on Opportunity (after insert,after update) {
  OpportunityUtility.triggerCall(Trigger.new);
}

 

----------------------------------------------------------------------------------------------

public  class OpportunityUtility {
 
  public static void triggerCall(List<Opportunity> opp){
    
    List<Opportunity> opp_up = new List<Opportunity>();
   
    for(Opportunity op : opp){
    
            os.OrderNumber__c = 'cusorder';
           opp_up.add(op);
    }

}

 

How to solve it................... need urgent.

 

Thanks,

Bujji