Hi I need to fetch the status field values from the Case History in order to set date/time on when the status was changed to a waiting state. While I was running this code I encountered a run time error System.FinalException: Record is read-only: Trigger.trackCase, I found that this is because the data is not submitted to data base and the field is read only. My question is, how to clone the record and perform the necessary field updates? Here is the trigger I have written.

trigger trackCase on Case (before update) {

     Set<Id> setId = new Set<Id>();
//   List<Case> ne = new List<Case>{}; 
     List<CaseHistory> ch = new List<CaseHistory>{};  
     Integer i = 0;
     for(Case con: trigger.new) {
         ch = [Select id,CaseId, Field, NewValue, OldValue from CaseHistory where CaseId = :setId  Limit 1];
     }  //  system.debug('&&&&&&&CaseHistory size&&&&&&&&&'+ch.size());
     // for(integer i=0;i<ch.size();i++)

     for(Case ne: setId) {
         for(CaseHistory c: ch) {
             if( ch[i].Field=='status' ) {
                 system.debug('&&&&&&&CaseHistory&& honey singh '+'Field '+c.Field +' Changed from ' +c.OldValue+' to ' +c.NewValue);

                 //con.Track_status_history__c = 'Field '+c.Field +' Changed from ' +c.OldValue+' to ' +c.NewValue;
                 if ((ch[i].OldValue != 'wait-cust-feedback' || ch[i].OldValue != 'wait-se-feedback' || ch[i].OldValue != 'wait-eng-feedback') && 
                     (ch[i].NewValue == 'wait-cust-feedback' || ch[i].NewValue == 'wait-se-feedback' || ch[i].NewValue == 'wait-eng-feedback')) {

                     ne.start_waiting_date__c = DateTime.Now(); 
                     System.debug('starts at' + ne.start_waiting_date__c);
                 } else if ((ch[i].OldValue == 'wait-cust-feedback' || ch[i].OldValue == 'wait-se-feedback' || ch[i].OldValue == 'wait-eng-feedback') && 
                            (ch[i].NewValue != 'wait-cust-feedback' || ch[i].NewValue != 'wait-se-feedback' || ch[i].NewValue != 'wait-eng-feedback')) {
                     ne.stop_waiting_date__c = DateTime.now();
                     System.debug('ends at' + ne.stop_waiting_date__c);

  • There are errors in your code due to which the code wont save at all. Perhaps a little cleaner code will help to get your answer faster. – AslamK Nov 12 '14 at 13:48

I do not see where you are trying to clone anything so I am assuming all you want to do it update some field values......Since you want case history I created a future method to run after the case is updated.

There are other things you will need to take into consideration like how you handle the logic if there is more than one case history record, etc of which there are various ways to handle it based on business requirements.

Also, I did not check the code for its ability to compile so you may have to tweak it a bit

Try this:

trigger trackCase on Case (after update) {

    if(!updatesCaseFields.stopCaseTrigger) updateCaseFields(trigger.newMap.Keyset());


public class updateCaseFields{

public static boolean stopCaseTrigger = false;

public static void populate fields(Set<ID> caseIDs){

     Case[] casesTBU = New Case[]{};
     Map<ID,List<CaseHistory>> caseToCaseHistory = new Map<ID,List<CaseHistory>>();  

     Integer i = 0;

     for(CaseHistory c: [Select id,CaseId, Field, NewValue, OldValue from CaseHistory where CaseId IN :caseIDs]) {
            caseToCaseHistory.put(c.caseID,New List<CaseHistory>());


     for(ID c : caseIDs) {

        List<CaseHistory> ch = caseToCaseHistory.get(caseID);
        Case updated_case = New Case(id = c);

        if(ch == null) continue;

             if( ch[0].Field=='status' ) {

                 if ((ch[0].OldValue != 'wait-cust-feedback' || ch[0].OldValue != 'wait-se-feedback' || ch[0].OldValue != 'wait-eng-feedback') && 
                     (ch[0].NewValue == 'wait-cust-feedback' || ch[0].NewValue == 'wait-se-feedback' || ch[0].NewValue == 'wait-eng-feedback')) {

                     updated_case.start_waiting_date__c = DateTime.Now();
                     System.debug('starts at' + updated_case.start_waiting_date__c);
                 } else if ((ch[0].OldValue == 'wait-cust-feedback' || ch[0].OldValue == 'wait-se-feedback' || ch[0].OldValue == 'wait-eng-feedback') && 
                            (ch[0].NewValue != 'wait-cust-feedback' || ch[0].NewValue != 'wait-se-feedback' || ch[0].NewValue != 'wait-eng-feedback')) {
                     updated_case.stop_waiting_date__c = DateTime.now();
                     System.debug('ends at' + updated_case.stop_waiting_date__c);

        stopCaseTrigger = true;
        update casesTBU;
        stopCaseTrigger = false;
| improve this answer | |
  • it complies but it does not provide the desired output. I need to update certain fields after the status has been changed. When I run the code the debug messages are not printed – user3482434 Nov 12 '14 at 14:32
  • @user3482434 - Ok. I updated my answer with an after trigger and a future method. I just did this real quick so you may have to tweak it – Eric Nov 12 '14 at 15:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.