+ Start a Discussion
DebjaniDebjani 

Map to identify records inside batchable class

I have a batchable class using which I am sharing groups to cases based on criteria. While I perform this I realize that I will need to fetch the cases
and perform a validation to check which of the cases have sharing already and which do not have. After which I will share groups only to cases which do not have the sharing. How do we achieve this using batch apex?
Best Answer chosen by Debjani
Prem Anandh 1Prem Anandh 1
Hi Lilly,
Following are the steps I have followed to achive this solution.
  • Created a checkbox field Is Shared and default is false. 
  • Query on Case object where Is Shared = false (i.e: record not yet shared) and Query will return not shared records
  • Query on Group object to get the Group Id. For now I used specific Group for sharing. 
  • Iterate the list of Case records and creating CaseShare for the same and Updating the shared record Case.Is Shared to true. So next time our batch will not process this record. 

Batch Code:
 
global class batchCaseUpdate implements Database.Batchable<sObject> {
    global Database.QueryLocator start(Database.BatchableContext BC) 
    {
        /*If you want you can add more condition based on your requirement. 
        Currently the condition will check the case is already assigned to any groups are not. Any one of case not assigned to group then it will execute the method */
        String query = 'SELECT Id FROM Case where Is_Shared__c = false';
        return Database.getQueryLocator(query);
    }
    global void execute(Database.BatchableContext BC, List<Case> lstCase) 
    {
        //To get the GroupId which we need to assign to Case.
        List<Group> lstGroup = new List<Group>([SELECT Id,DeveloperName FROM Group where DeveloperName = 'Case_Sharing']);        
        List<CaseShare> lstCaseShare = new List<CaseShare>();
        
        //If given groups are available in org then condition will execute else it won't exeute anything
        if(!lstGroup.isEmpty())
            for(Case objCase :  lstCase)
            {
                lstCaseShare.add(new CaseShare(CaseId = objCase.Id, UserOrGroupId = lstGroup[0].Id, CaseAccessLevel ='Edit'));
                objCase.Is_Shared__c = true;
            }
            
        Database.Insert(lstCaseShare, true);  
        Database.Update(lstCase, true);  
    }
    global void finish(Database.BatchableContext BC) 
    {
    
        
    }
}

Hope it will help for you. Please let me know incase any queries. 

Thanks,
Prem Anandh
 

All Answers

Ravi Dutt SharmaRavi Dutt Sharma
Query on CaseShare and get all the Case id's.
 
[SELECT CaseId FROM CaseShare]

In this way you will have all the case id's for which sharing records exist. Store these case id's in a set.
Now query all the case records and store id's in another set. Use contains method to find the difference in set 1 and set 2 and store the difference in set 3.
Prem Anandh 1Prem Anandh 1
Are you going to share any specific groups?  or Multiple Group?

If Multiple Groups are there, then what is the criteria to populate the Group?
Prem Anandh 1Prem Anandh 1
Hi Lilly,
Following are the steps I have followed to achive this solution.
  • Created a checkbox field Is Shared and default is false. 
  • Query on Case object where Is Shared = false (i.e: record not yet shared) and Query will return not shared records
  • Query on Group object to get the Group Id. For now I used specific Group for sharing. 
  • Iterate the list of Case records and creating CaseShare for the same and Updating the shared record Case.Is Shared to true. So next time our batch will not process this record. 

Batch Code:
 
global class batchCaseUpdate implements Database.Batchable<sObject> {
    global Database.QueryLocator start(Database.BatchableContext BC) 
    {
        /*If you want you can add more condition based on your requirement. 
        Currently the condition will check the case is already assigned to any groups are not. Any one of case not assigned to group then it will execute the method */
        String query = 'SELECT Id FROM Case where Is_Shared__c = false';
        return Database.getQueryLocator(query);
    }
    global void execute(Database.BatchableContext BC, List<Case> lstCase) 
    {
        //To get the GroupId which we need to assign to Case.
        List<Group> lstGroup = new List<Group>([SELECT Id,DeveloperName FROM Group where DeveloperName = 'Case_Sharing']);        
        List<CaseShare> lstCaseShare = new List<CaseShare>();
        
        //If given groups are available in org then condition will execute else it won't exeute anything
        if(!lstGroup.isEmpty())
            for(Case objCase :  lstCase)
            {
                lstCaseShare.add(new CaseShare(CaseId = objCase.Id, UserOrGroupId = lstGroup[0].Id, CaseAccessLevel ='Edit'));
                objCase.Is_Shared__c = true;
            }
            
        Database.Insert(lstCaseShare, true);  
        Database.Update(lstCase, true);  
    }
    global void finish(Database.BatchableContext BC) 
    {
    
        
    }
}

Hope it will help for you. Please let me know incase any queries. 

Thanks,
Prem Anandh
 
This was selected as the best answer
DebjaniDebjani

Hi Prem,

The criteria lies in querying the case based on a field say ABC which contains value, say "Time" , so it should be shared with only those Groups with name containing "Time".

Your approach is correct. But if I do not create a field on page like you have mentioned , "IsShared" checkbox or do not have any such field to check if it is shared,(we have a button through which we check it) can we use the same way?

 

Prem Anandh 1Prem Anandh 1
Hi Lilly, 

I don't think for default option to check the case is already shared or not. So I used custom checkbox to find this criteria.