function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
TBouscalTBouscal 

Apex data validation

Attempting to create a validation rule that insures the end user closing a Case has already entered a Comment on that Case but I can't seem to get the map to work correctly.  Here's what I have in the trigger; 
trigger Cases on Case (<etc>){

    if(Trigger.isBefore && Trigger.isUpdate){

             CloseValidation.CheckValidation(Trigger.new); 

    }
}
and here's the class; 
public class CloseValidation {
    public static void CheckValidation(Case[] cs) 
    {
        if(UserInfo.getProfileId()!='00e30000000d2ft'){ // bypass for Salesforce Administrator profile //
            map<Id, CaseComment> CaseCommentMap = new map<Id, CaseComment>();
            Id thisUser = UserInfo.getUserId();
            
            for (Case c:cs){
                if(c.Status=='Closed' && c.RecordTypeId=='01270000000Q9E1'){
                    CaseCommentMap.Put(c.id,null);
                }
            }
            CaseCommentMap.remove(null);
            CaseCommentMap.putAll([Select Id FROM CaseComment Where ParentId in : CaseCommentMap.keyset() AND CreatedById =:thisUser]);
            
            // if CaseCommentMap has a null for the CaseComment then error
            for(Case c:cs){
                if(!CaseCommentMap.containsKey(c.id) && c.Status=='Closed'){
                    // no key - fail
                    c.addError('You must have commented to close the case (CaseValidation.apx) ' + c.id );         
                } else {
                    // has key - pass
                }
            }      
        }
    }
}

What am I overlooking?
 
Best Answer chosen by TBouscal
Amit Singh 1Amit Singh 1
Hi,

You are doing wrong CaseCommentMap.putAll([Select Id FROM CaseComment Where ParentId in : CaseCommentMap.keyset() AND CreatedById =:thisUser]); line . In this case Map will contain CaseComment Id as Key and CaseComment as a value and then this will never pass if(!CaseCommentMap.containsKey(c.id) && c.Status=='Closed') and you will always get Error.

I have made some tweaked and below are the code for both trigger and Class.

Trigger.
trigger Cases on Case (before Update){

    if(Trigger.isBefore && Trigger.isUpdate){

             CloseValidation.CheckValidation(Trigger.new, Trigger.oldMap); 

    }
}
Class.
 
public class CloseValidation {
    public static void CheckValidation(Case[] cs, Map<Id, case> oldCases) 
    {
        if(UserInfo.getProfileId()!='00e30000000d2ft'){ // bypass for Salesforce Administrator profile //
            map<Id, List<CaseComment>> CaseCommentMap = new map<Id, List<CaseComment>>();
            Id thisUser = UserInfo.getUserId();
            Set<Id> caseIdsSet = new Set<Id>();
            for (Case c:cs){
                if(c.Status=='Closed' && oldCases.get(c.id).Status!='Closed'){
                    caseIdsSet.add(c.id);
                }
            }
            //CaseCommentMap.remove(null);
            For(CaseComment c : [Select ParentID FROM CaseComment Where ParentId 
                                        in:caseIdsSet AND CreatedById =:thisUser]){
                  If(!CaseCommentMap.containsKey(c.ParentId)){
                      CaseCommentMap.put(c.ParentId, new List<CaseComment>{c});
                  }else{
                      List<CaseComment> casecommentList = CaseCommentMap.get(c.ParentId);
                      CaseCommentMap.put(c.ParentId,casecommentList);
                  }
                                        
            }
            
            System.debug('#### CaseCommentMap = '+CaseCommentMap);
            // if CaseCommentMap has a null for the CaseComment then error
            for(Case c:cs){
                System.debug('#### Case ID = '+c.id);
                if(!CaseCommentMap.containsKey(c.id) && c.Status=='Closed' && oldCases.get(c.id).Status!='Closed'){
                    // no key - fail
                    c.addError('You must have commented to close the case (CaseValidation.apx) ' + c.id );         
                } else {
                    // has key - pass
                }
            }      
        }
    }
}
Let me know the outcomes.
Thanks,
Amit Singh.

All Answers

Amit Singh 1Amit Singh 1
Hi,

You are doing wrong CaseCommentMap.putAll([Select Id FROM CaseComment Where ParentId in : CaseCommentMap.keyset() AND CreatedById =:thisUser]); line . In this case Map will contain CaseComment Id as Key and CaseComment as a value and then this will never pass if(!CaseCommentMap.containsKey(c.id) && c.Status=='Closed') and you will always get Error.

I have made some tweaked and below are the code for both trigger and Class.

Trigger.
trigger Cases on Case (before Update){

    if(Trigger.isBefore && Trigger.isUpdate){

             CloseValidation.CheckValidation(Trigger.new, Trigger.oldMap); 

    }
}
Class.
 
public class CloseValidation {
    public static void CheckValidation(Case[] cs, Map<Id, case> oldCases) 
    {
        if(UserInfo.getProfileId()!='00e30000000d2ft'){ // bypass for Salesforce Administrator profile //
            map<Id, List<CaseComment>> CaseCommentMap = new map<Id, List<CaseComment>>();
            Id thisUser = UserInfo.getUserId();
            Set<Id> caseIdsSet = new Set<Id>();
            for (Case c:cs){
                if(c.Status=='Closed' && oldCases.get(c.id).Status!='Closed'){
                    caseIdsSet.add(c.id);
                }
            }
            //CaseCommentMap.remove(null);
            For(CaseComment c : [Select ParentID FROM CaseComment Where ParentId 
                                        in:caseIdsSet AND CreatedById =:thisUser]){
                  If(!CaseCommentMap.containsKey(c.ParentId)){
                      CaseCommentMap.put(c.ParentId, new List<CaseComment>{c});
                  }else{
                      List<CaseComment> casecommentList = CaseCommentMap.get(c.ParentId);
                      CaseCommentMap.put(c.ParentId,casecommentList);
                  }
                                        
            }
            
            System.debug('#### CaseCommentMap = '+CaseCommentMap);
            // if CaseCommentMap has a null for the CaseComment then error
            for(Case c:cs){
                System.debug('#### Case ID = '+c.id);
                if(!CaseCommentMap.containsKey(c.id) && c.Status=='Closed' && oldCases.get(c.id).Status!='Closed'){
                    // no key - fail
                    c.addError('You must have commented to close the case (CaseValidation.apx) ' + c.id );         
                } else {
                    // has key - pass
                }
            }      
        }
    }
}
Let me know the outcomes.
Thanks,
Amit Singh.
This was selected as the best answer
TBouscalTBouscal
Thank you very much Amit!  Added my criteria for record type, modified my test a little and everything is gold!