TransWikia.com

Is there a way to programmatically deactivate Proces Builder & flows?

Salesforce Asked by Jenssen on December 27, 2020

Is there a way to soql procesbuilder to tun activation off?

For example

List<Processbuilder> pbColl = new List<Processbuilder>();  
Processbuilder pb=[SELECT status FROM Processbuilder WHERE status Active];

for(Processbuilder turnoff : pb){
            turnoff.status = false;
            pbColl.add(pb)}
update pbColl;

If not is there a simple way to turn all activated Processes off/on?

4 Answers

If you want to be able to "flip a switch" in code to disable Process Builders, you could use a boolean Custom Setting field. Then update your Process Builders so that the very first entry criterion is the custom setting being true, and if it is not, stop. Then from Apex you will be able to set the Custom Setting field to false whenever you need to stop the processes from executing.

Correct answer by Charles T on December 27, 2020

This is possible by using the Tooling API. There are three steps required to

  1. find active processes and store their information in the org
  2. switch all processes OFF
  3. switch all prior active processes back ON again

Copy the following code, paste it in anonymous Apex window in the Developer Console. Highlight each step (start and end marked in code) and execute consecutively.

I've done the same with Validation Rules, check on GitHub: ValidationRuleOnOff

/**
* ─────────────────────────────────────────────────────────────────────────────────────────────────┐
* Anonymous Apex to switch ON/OFF active Processes in Process Builder (Flow Definitions)
*
* Execute Step 1-3 anonymous to 
* * [Step 1:] find all active Processes in the org >> Store their Data in Cases
* * [Step 2:] turn all Processes OFF (Metadata -> activeVersionNumber -> null)
* * [Step 3:] turn all Processes back ON (active:true)
*
* All prior active Processes will be re-activated. 
* Data Storage Cases will be delted at the end of Step 3.
* ──────────────────────────────────────────────────────────────────────────────────────────────────
* @author         Heiko Krämer   <[email protected]>
* @created        2020-10-24
* ─────────────────────────────────────────────────────────────────────────────────────────────────┘
*/

// START STEP 1 -> "QUERY FLOW DEFINITIONS, STORE FD DATA"
// Retreive active FlowDefinition from Org, store their URL and Metadata in Cases
List<Id> listOfFlowDefinitionIds       = new List<Id>();
List<Case> flowDefinitionStorageCases  = new List<Case>();
Integer flowDefinitionsProcessed       = 0;
 
// Tooling API Call to receive IDs for all active FlowDefinitions
String toolingSOQL = '/services/data/v49.0/tooling/query?q=Select+Id+From+FlowDefinition';
String baseURL     = URL.getSalesforceBaseUrl().toExternalForm();
String endpoint    = baseURL + toolingSOQL;
 
Http NewReq        = new Http();
HttpRequest hreq   = new HttpRequest();
 
hreq.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionId());
hreq.setTimeout(60000);
hreq.setEndpoint(endPoint);
hreq.setMethod('GET');
HttpResponse hresp = NewReq.send(hreq);
 
String body = hresp.getBody();
System.debug('ResponseBody' + body);
 
// Parse JSON response for IDs >> store IDs in List.
JSONParser parser = JSON.createParser(hresp.getBody());
while (parser.nextToken() != null) {
    if ((parser.getCurrentToken() == JSONToken.FIELD_NAME) &&
        (parser.getText() == 'Id')) {
            parser.nextToken();
            listOfFlowDefinitionIds.add(parser.getIdValue());
        }
}
 
// Loop through FlowDefinition IDs and query all Metadata info via Tooling API
for (Id valId : listOfFlowDefinitionIds) {
    String valIdString = ''' + valId + ''';
    String toolingSOQL = '/services/data/v48.0/tooling/query/?q=Select+Metadata+From+FlowDefinition+Where+Id+=+';
    String baseURL     = URL.getSalesforceBaseUrl().toExternalForm();
    String endpoint    = baseURL + toolingSOQL + valIdString;
   
    Http NewReq        = new Http();
    HttpRequest hreq   = new HttpRequest();
   
    hreq.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionId());
    hreq.setTimeout(60000);
    hreq.setEndpoint(endPoint);
    hreq.setMethod('GET');
    HttpResponse hresp = NewReq.send(hreq);
   
    String body = hresp.getBody();
    system.debug('ResponseBody' + body);
    system.debug('Length' + body.length());
   
    
    // Create cases to store data from active FlowDefinition
    // Case Subject is used to store the FlowDefinition endpoint URL
    // Case Description is used to store FlowDefinition Metadada
   
    If (!body.contains('"activeVersionNumber":null')){
        flowDefinitionsProcessed = flowDefinitionsProcessed + 1;
       
        case flowDefinitionStorageCase        = new case();
        flowDefinitionStorageCase.subject     = '/services/data/v48.0/tooling/sobjects/FlowDefinition/' + valId + '# FD' + flowDefinitionsProcessed;
        flowDefinitionStorageCase.description = '{"Metadata' + body.substringAfter('Metadata').removeEnd(']}');
        flowDefinitionStorageCase.origin      = 'Web';
        flowDefinitionStorageCase.status      = 'Closed';
        flowDefinitionStorageCases.add(flowDefinitionStorageCase);
    }
}
insert flowDefinitionStorageCases;
// END STEP 1


// START STEP 2 -> "SWITCH Processes OFF"
// SOQL all prior created cases >> update "activeVersionNumber" to "null" >> process PATCH Calls
List<Case> retrievedFlowDefinitionCases = new List<Case>([SELECT Id, Subject, Description
                                                            FROM Case
                                                           WHERE Subject
                                                            LIKE '%tooling/sobjects/FlowDefinition%']);
system.debug('Number of Cases: ' + retrievedFlowDefinitionCases.size());
 
for (Case flowDefinition : retrievedFlowDefinitionCases){
    String flowDefinitionUrl      = flowDefinition.Subject.substringBeforeLast('# FD');
    String flowDefinitionMetadata = flowDefinition.Description.replace(flowDefinition.Description.substringBetween('activeVersionNumber":', ',"description'), 'null');
    Http h                        = new Http();
    HttpRequest req               = new HttpRequest();
    req.setEndpoint(URL.getSalesforceBaseUrl().toExternalForm() + flowDefinitionUrl);
    req.setBody(flowDefinitionMetadata);
    req.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionId());
    req.setHeader('Content-Type', 'application/json');
    req.setMethod('PATCH');
    HttpResponse res = h.send(req);
    system.debug('HttpRequest: ' + req);  
} // END STEP 2


// START STEP 3 -> "SWITCH FLOW DEFINITION ON"
// SOQL all prior created cases >> process PATCH Calls to restore initial state >> delete all prior created cases
List<Case> retrievedFlowDefinitionCases = new List<Case>([SELECT Id, Subject, Description
                                                            FROM Case
                                                           WHERE Subject
                                                            LIKE '%tooling/sobjects/FlowDefinition%']);
System.debug('Number of Cases: ' + retrievedFlowDefinitionCases.size());
 
for (Case flowDefinition : retrievedFlowDefinitionCases){
    String flowDefinitionUrl      = flowDefinition.Subject.substringBeforeLast('# FD');
    String flowDefinitionMetadata = flowDefinition.Description;
    Http h                        = new Http();
    HttpRequest req               = new HttpRequest();
    req.setEndpoint(URL.getSalesforceBaseUrl().toExternalForm() + flowDefinitionUrl);
    req.setBody(flowDefinitionMetadata);
    req.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionId());
    req.setHeader('Content-Type', 'application/json');
    req.setMethod('PATCH');
    HttpResponse res = h.send(req);
}
delete retrievedFlowDefinitionCases;
// END STEP 3

Answered by Heiko on December 27, 2020

Ben Edwards has a set of tools which includes one called Salesforce Switch which enabled you to do this.

He has also put the source code on GitHub:

I also wrote a lightning component to allow on mass enable/disable:

At it's core, it uses the Tooling API.

Getting Flow/Process Info

GET: /services/data/v43.0/tooling/query?q=Select+Id,ActiveVersion.VersionNumber,LatestVersion.VersionNumber,DeveloperName+From+FlowDefinition+ORDER+BY+DeveloperName

Updating Flow/Process Info

POST: /services/data/v43.0/tooling/sobjects/FlowDefinition/{FlowId}/?_HttpMethod=PATCH

With JSON:

{
  'Metadata': {
       'activeVersionNumber': {versionNumber/null}
   }
}

NOTE: the ?_HttpMethod=PATCH is only required if your calling from Apex

Answered by Robs on December 27, 2020

Not natively in Apex. You'd need to use the Tooling API and query InteractionDefinitionVersion. See also: Error - Failed To Execute Flow - 301 Prefix - Process Builder That would allow you to query for the data, but I don't think you'd be able to turn the flows on/off this way. You may be having a bit of an X-Y Problem. You will generally get better answers if you describe your high level objective rather than the specific means you are pursuing to achieve it.

Answered by Adrian Larson on December 27, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP