+ Start a Discussion
James Sanford 6James Sanford 6 

Why is my apex class inserting comments twice?

I have an apex class that copies data from a custom field on the close case screen  into case comments when the case is closed, however it is creating the comments twice each time.  Can anyone tell me why it is doing this and how I can fix it?  Below is the apex class;

public without sharing class CaseManagement {
    
    //*****************************************************************************
  //Method called on after update of Case
  //****************************************************************************/
  public static void onAfterUpdate(List<Case> lstCase, Map<Id, Case> oldMap){ 
    checkCloseCase(lstCase, oldMap);   
  } 

  //*****************************************************************************
  //Method called to check the Close Case
  //****************************************************************************/
  public static void checkCloseCase(List<Case> lstCase, Map<Id, Case> oldMap) { 
    
    List<CaseComment> comments = new List<CaseComment>();
               
    for(Case caseUpdate : lstCase) {
            
      if( caseUpdate.Case_Close_Notes_To_Customer__c != null && caseUpdate.Case_Close_Notes_To_Customer__c != oldMap.get(caseUpdate.Id).Case_Close_Notes_To_Customer__c) {
        comments.add( new CaseComment(CommentBody = caseUpdate.Case_Close_Notes_To_Customer__c, IsPublished = false, ParentId = caseUpdate.Id));
      }
    }
    insert comments;
  }
}
Best Answer chosen by James Sanford 6
Alexander TsitsuraAlexander Tsitsura
Hi James,

Do u have any workflow rules on Case object? If the record was updated with workflow field updates, fires before update triggers and after update triggers one more time. 

Here are the steps:
  1. Executes after triggers
  2. Executes workflow rules
  3. Executes all after triggers(with the same old Map).
Workaround:
For preventing this, u can create static Set to check if its case processed before.
 
public without sharing class CaseManagement {
    
  private static Set<Id> idSet  = new Set<Id>();

  //*****************************************************************************
  //Method called on after update of Case
  //****************************************************************************/
  public static void onAfterUpdate(List<Case> lstCase, Map<Id, Case> oldMap){ 
     checkCloseCase(lstCase, oldMap);   
  } 

  //*****************************************************************************
  //Method called to check the Close Case
  //****************************************************************************/
  public static void checkCloseCase(List<Case> lstCase, Map<Id, Case> oldMap) { 
    
    List<CaseComment> comments = new List<CaseComment>();
               
    for(Case caseUpdate : lstCase) {
            
     // check if case processed before
     if (idSet.contains(caseUpdate.Id)) {
        continue; // skip case, processed before
     } else {
        idSet.add(caseUpdate.Id);
     }
     
      if( caseUpdate.Case_Close_Notes_To_Customer__c != null && caseUpdate.Case_Close_Notes_To_Customer__c != oldMap.get(caseUpdate.Id).Case_Close_Notes_To_Customer__c) {
        comments.add( new CaseComment(CommentBody = caseUpdate.Case_Close_Notes_To_Customer__c, IsPublished = false, ParentId = caseUpdate.Id));
      }
    }
    insert comments;
  }
}
As a common practice, if your question is answered, please choose 1 best answer. 
But you can give every answer a thumb up if that answer is helpful to you.

Thanks,
Alex

All Answers

Alexander TsitsuraAlexander Tsitsura
Hi James,

Do u have any workflow rules on Case object? If the record was updated with workflow field updates, fires before update triggers and after update triggers one more time. 

Here are the steps:
  1. Executes after triggers
  2. Executes workflow rules
  3. Executes all after triggers(with the same old Map).
Workaround:
For preventing this, u can create static Set to check if its case processed before.
 
public without sharing class CaseManagement {
    
  private static Set<Id> idSet  = new Set<Id>();

  //*****************************************************************************
  //Method called on after update of Case
  //****************************************************************************/
  public static void onAfterUpdate(List<Case> lstCase, Map<Id, Case> oldMap){ 
     checkCloseCase(lstCase, oldMap);   
  } 

  //*****************************************************************************
  //Method called to check the Close Case
  //****************************************************************************/
  public static void checkCloseCase(List<Case> lstCase, Map<Id, Case> oldMap) { 
    
    List<CaseComment> comments = new List<CaseComment>();
               
    for(Case caseUpdate : lstCase) {
            
     // check if case processed before
     if (idSet.contains(caseUpdate.Id)) {
        continue; // skip case, processed before
     } else {
        idSet.add(caseUpdate.Id);
     }
     
      if( caseUpdate.Case_Close_Notes_To_Customer__c != null && caseUpdate.Case_Close_Notes_To_Customer__c != oldMap.get(caseUpdate.Id).Case_Close_Notes_To_Customer__c) {
        comments.add( new CaseComment(CommentBody = caseUpdate.Case_Close_Notes_To_Customer__c, IsPublished = false, ParentId = caseUpdate.Id));
      }
    }
    insert comments;
  }
}
As a common practice, if your question is answered, please choose 1 best answer. 
But you can give every answer a thumb up if that answer is helpful to you.

Thanks,
Alex
This was selected as the best answer
James Sanford 6James Sanford 6
Thanks Alex, that really helped.