Tag Archives: Approval Process

Set Approval Process Lock And Unlock Records Using Apex Code

Sometimes we have faced business requirement to Lock or Unlock records in Salesforce. We can use apex lock() and unlock() methods in the System.Approval namespace to lock and unlock records by passing in record IDs or sObjects.

To enable this feature, go to Setup | Search Automation Settings in the Quick Find box | click on Automation Settings. Then, select Enable record locking and unlocking in Apex.

Lock Record Example:

//Get records to lock
List<case> caseList = [SELECT Id From Case LIMIT 10];
//Lock records
List<Approval.LockResult> lrList = Approval.lock(caseList, false);

// Iterate through each returned result
for(Approval.LockResult lr : lrList) {
    if (lr.isSuccess()) {
        //Operation was successful, so get the ID of the record that was processed
        System.debug('Successfully locked account with ID: ' + lr.getId());
    }
    else {
        //Operation failed, so get all errors                
        for(Database.Error err : lr.getErrors()) {
            System.debug('The following error has occurred.');                    
            System.debug(err.getStatusCode() + ': ' + err.getMessage());
            System.debug('Case fields that affected this error: ' + err.getFields());
        }
    }
}

Unlock Record Example:

//Get records to unlock
List<case> caseList = [SELECT Id From Case LIMIT 10];
//Check locked records
List<case> caseLockList = new List<Case>();
for(Case c :caseList){
    if(Approval.isLocked(c.id)){
        caseLockList.add(c);
    }
}
//Unlock record
if(!caseLockList.isEmpty()){
    //Unlock records
    List<Approval.UnlockResult> ulrList = Approval.unlock(caseLockList, false);
    
    // Iterate through each returned result
    for(Approval.UnlockResult  ulr : ulrList) {
        if (ulr.isSuccess()) {
            //Operation was successful, so get the ID of the record that was processed
            System.debug('Successfully locked account with ID: ' + ulr.getId());
        }
        else {
            //Operation failed, so get all errors                
            for(Database.Error err : ulr.getErrors()) {
                System.debug('The following error has occurred.');                    
                System.debug(err.getStatusCode() + ': ' + err.getMessage());
                System.debug('Case fields that affected this error: ' + err.getFields());
            }
        }
    }
}

Recall Approval Process Using Apex In Salesforce

Sample Code:

//Object record id to recall the approval process
String recordId = '0065800000lQxxsAAC';
//Get Process Instance Work Items
ProcessInstanceWorkitem[] piWorkItems = [SELECT Id FROM ProcessInstanceWorkItem WHERE ProcessInstance.TargetObjectId = :recordId
                                         AND ProcessInstance.Status = 'Pending']; 
if(piWorkItems.size() > 0){
    //Create Process Work Item Request
    Approval.ProcessWorkItemRequest pwiRequest = new Approval.ProcessWorkItemRequest();
    pwiRequest.setAction('Removed');
    pwiRequest.setWorkItemId(piWorkItems[0].Id);
    Approval.ProcessResult result = Approval.process(pwiRequest);
}

Salesforce Sandbox Workflow & Approval Process email alert not working

Its the effect from Spring release13 all the Sandboxes Access Email level are set default to “System Emails” only, We need to change it here -> Setup -> Email Administration -> Deliverability -> set the Access to Send Email from “System Only” to “All Emails”.

Restrict multiple approval for a single user to a single record in Salesforce

I had a requirement to restrict multiple approval for a single user to a single record. There were multiple steps of approval process and the approver may be in different queue or as a manager for a user.

So, I implemented it using a trigger. In this article I’ll demonstrate how to implement it.
Here Application__c is the object, on which 3 steps approval process has implemented.
A custom check box field Check_Approver__c has set value to true, in all 3 steps field update action.

In below trigger I filtered the ProcessInstanceStep object records with current user Id in ActorId and the object Id (here object Id means record Id) in ProcessInstance.TargetObjectId.

  • If an User will approve or reject a record, then the SOQL query will return a single record.
  • If the SOQL query return a record, then trigger will throw an error message.

Trigger source code:

trigger ApplicationTrigger on Application__c (before Update)
{
    if(trigger.isUpdate){

        Id currentUserId = UserInfo.getUserId();
        for(Application__c sf: trigger.new){   
                  
            if(sf.Check_Approver__c == true){
              
                List<processinstancestep> existingApprovals = [SELECT ActorId
                                    FROM ProcessInstanceStep WHERE ProcessInstance.TargetObjectId = :sf.Id
                                    AND (StepStatus = 'Approved' OR StepStatus = 'Rejected')
                                    AND ActorId = :currentUserId];
                                      
                if(existingApprovals != null){
                  
                    if(existingApprovals.size() > 0){

                        sf.addError('You have already approved or rejeted the record.');
                    }
                }                  
             }
         }                         
    }
}