7

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?

6 Answers 6

2

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.

3

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

1

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.

1

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
0

At present time, there is a way to switch on/off process builder. You can utilize Hierarchical custom setting. Which lets you define setting specific to Org Level, Profile Level or User Level.

While creating a custom setting select the type as - "Hierarchy". Now this setting would be created similar to custom object, having suffix - __c. Now create your own custom field of type checkbox so that its boolean value can be utilized into process builder.

Now define the values specific to Profile or User level. So that it will provide relevant value (specific to profile or user through which current execution is being processed).

In the process builder you would be able to call it via formula field as - $Setup.customSettingName__c.customFieldName__c to check whether current user has the right to execute the process builder or not.

For more detail, please refer the following links -

  1. https://developer.salesforce.com/docs/atlas.en-us.236.0.apexref.meta/apexref/apex_methods_system_custom_settings.htm
  2. https://medium.com/@pankajsingh210/salesforce-hierarchy-custom-settings-d6e1dcce75d
0

I've taken @Robs Lightning Component and built on it, adding:

  • The ability to save the state of all your flows and process builders before you start disabling flows
  • The ability to restore all your flows and process builders to the state that they were in when you started or to your most recently saved state
  • When restoring from saved state, the same version of the flow/process builder that was previously active is made active again. Previously it always reactivated the latest version, regardless of which was previously active
  • Feedback when you carry out operations (although it could be improved)
  • A couple of minor bug fixes

It's available in a github repository here along with a demo video and details installation instructions in the readme

I tried @Heiko's version but it runs out if you have more than 50 flows and Process Builders due to hitting callout limits. I also wasn't keen on adding data (cases) to an org that could end up distorting business reporting. This is why I used a private Note record to record the previous state of active flows/processes. Notes must be enabled in the org before using my method, but this is not an irreversible change in Salesforce as Notes can be disabled afterwards if you really don't want them switched on in your org.

Ben Edwards tool can't handle large numbers of flows (probably due to APEX limits) and you end up having to select several flows at a time then run-re-run the tool.

Mine is the only solution I've found which avoids the callout limit as it disables each flow/process builder in a separate APEX transaction.

It is also the only solution which allows you to save the state before you start, make any changes you like in terms of enabling/disabling flows, then restore your org to the state it was in before you started, including the flow or process builder version which was previously active.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .