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
conradvillaconradvilla 

Lookup Record ID in Flow for use in Dynamic Choice

Does anyone know a good way to query and set the 15 byte RecordType ID in Flow to be able to assign it to a variable for use in a dynamic choice?

 

I have a lookup element that queries 'RecordType" for a record where DeveloperName == 'Client' and SobjectType == 'Account' to set the vaAccountRecordTypeID == id  HOWEVER it sets the variable as the 18 byte string and when I use it as part of my criteria for the Dynamic Choice it does not return any choices.  I then hard coded the 15 byte GUID for the RecordType id to the variable and it does find the record.  I really dont want to have to hard code this value.  I was also trying to see if there was a way to

Left(vaAccountRecordTypeID,15) in a text template to then set that as vaAccountRecordTypeID but had no luck getting that to work.

 

Has anyone found a way to overcome this shortcoming in VisualFlow.  It would be nice if you can just use the developername and SobjectType when defining the dynamic choice.

Best Answer chosen by Admin (Salesforce Developers) 
conradvillaconradvilla

OK, so the only way we were able to get around the issue, was to write an Apex Plug-in

 

global class flowGetRTId implements Process.Plugin { 

// The main method to be implemented. The Flow calls this at runtime.
global Process.PluginResult invoke(Process.PluginRequest request) { 
        
        String theObject = (String) request.inputParameters.get('Object');
        String theName = (String) request.inputParameters.get('Name');

        // Using the Object and Name provided attempt to find the Record Type
        List<RecordType> theList = [Select Id, DeveloperName, SObjectType from RecordType Where DeveloperName =:theName And SObjectType =:theObject LIMIT 1];
        
        String truncatedId = null;
        if(!theList.isEmpty()){
            truncatedId = String.valueOf(theList[0].Id).left(15);
        }
        // return to Flow
        Map<String,Object> result = new Map<String,Object>(); 
        result.put('RTId',truncatedId);
        return new Process.PluginResult(result); 
    } 

    // Returns the describe information for the interface
    global Process.PluginDescribeResult describe() { 
        Process.PluginDescribeResult result = new Process.PluginDescribeResult(); 
        result.Name = 'flowGetRTId';
        result.inputParameters = new 
           List<Process.PluginDescribeResult.InputParameter>{
               new Process.PluginDescribeResult.InputParameter('Object', Process.PluginDescribeResult.ParameterType.STRING, true),
               new Process.PluginDescribeResult.InputParameter('Name', Process.PluginDescribeResult.ParameterType.STRING, true)   
            };
        result.outputParameters = new 
           List<Process.PluginDescribeResult.OutputParameter>{
               new Process.PluginDescribeResult.OutputParameter('RTId', Process.PluginDescribeResult.ParameterType.STRING)
           }; 
        return result; 
    }

    static testmethod void TestflowGetRTId() {
        flowGetRTId plugin = new flowGetRTId();
        
        // return the Describe results
        Process.PluginDescribeResult thisDescribe = plugin.describe();
        
        // Create default values for each of the expected params
        Map<String,Object> inputParams = new Map<String,Object>();
        
        // As we cannot insert Record Types we must assume that there is a Client Record Type for Accounts
        InputParams.put('Object', 'Account');
        InputParams.put('Name', 'Client');

        Process.PluginRequest request = new Process.PluginRequest(inputParams);  
        
        // Run the plugin
        Process.PluginResult result;
        result = plugin.invoke(request);
        
        // Since we can not insert Record Types testing to verify whether the ID returned is not necessarily repeatable.
        // Therefore we are commenting out the following test
        // System.assertEquals('012700000005bVu',result.outputParameters.get('RTId'));
    } 
    
    static testmethod void testFlowGetRTId_NoResults() {
        flowGetRTId plugin = new flowGetRTId();
        Map<String,Object> inputParams = new Map<String,Object>();
    // Test 1
        // Create params which should not return any Record Types, invalid Object names or missing values
        InputParams.put('Object', 'TestObject1234567890');
        InputParams.put('Name', '');
        
        // Run the plugin
        Process.PluginRequest request = new Process.PluginRequest(inputParams);  
        Process.PluginResult result;
        result = plugin.invoke(request);

        // Verify that NULL is returned
        System.assertEquals(null,result.outputParameters.get('RTId'));
    // Test 2
        // Create params which should not return any Record Types, invalid Object names or missing values
        InputParams.put('Object', 'Account');
        InputParams.put('Name', 'NotARealRecordType');
        
        // Run the plugin
        request = new Process.PluginRequest(inputParams);  
        result = plugin.invoke(request);

        // Verify that NULL is returned
        System.assertEquals(null,result.outputParameters.get('RTId'));
    // Test 3
        // Create params which should not return any Record Types, invalid Object names or missing values
        InputParams.put('Object', 'Account');
        InputParams.put('Name', '');
        
        // Run the plugin
        request = new Process.PluginRequest(inputParams);  
        result = plugin.invoke(request);

        // Verify that NULL is returned
        System.assertEquals(null,result.outputParameters.get('RTId'));
    // Test 4
        // Create params which should not return any Record Types, invalid Object names or missing values
        InputParams.put('Object', '');
        InputParams.put('Name', 'Client');
        
        // Run the plugin
        request = new Process.PluginRequest(inputParams);  
        result = plugin.invoke(request);

        // Verify that NULL is returned
        System.assertEquals(null,result.outputParameters.get('RTId'));

 

All Answers

DarrellDDarrellD

I'm not familiar with the limitation you are referencing, but we've been using RecordTypes as Dynamic Choices for a while.

 

So I'm clear though, you are actually trying to do a dynamic choice on another object and you are filtering based on the record types? So you are saying something like "Contact Record Type = vaRecordTyhpeId" and displaying all relevant Contacts (or whatever the object is)?

conradvillaconradvilla

Yes, I have to query the RecordType object to return the Record Type ID for Accounts with a Record Type of 'Client' (DeveloperName) to then use in my Dynamic Choice to only return Account of that Record  Type.  However, it expects the 15 byte version not the 18 byte version

RajaramRajaram
Not sure what you are trying to do..
I just tried to create a dynamic choice with the following criteria
SObject equals Case
id equals 012D00000007AuiIAE

as well as:
SObject equals Case
id equals 012D00000007Aui

In both the cases, the dynamic choice worked correctly...

A good way is to log into the org using tools such as SOQL explorer (on mac) or the IDE to get the IDs and make sure there match correctly
conradvillaconradvilla

It doesn't work for me.  If in the dynamic choice I hard code Account Record Type == '012700000005bVu' It works, but If i do a record lookup that assigned the looked up record type ID to a variable, it doesn't work.  In my case the look up assigns a value of '012700000005bVuAAI' to vaAccountRecordType

 

Settings for Record Look up:

 

Lookup:  RecordType

 

DeveloperName == 'Client'

SobjectType == 'Account'

 

Sets id = vaAccountRecordTypeId 

 

That will return 012700000005bVuAAI

 

If on the Dynamic Choice I use the hard coded '012700000005bVu' I get results in my Dynamic Choice and when I replace the hard code with the variable, I get noting.  The variable is is both Input/Output and set to a Data Type of Text.

 

I tried Hard Coding 012700000005bVuAAI (18 byte version) into the Dynamic Choice and got the same results as using the variable, which is nothing.

 

 

 

DarrellDDarrellD
This must be unique to doing a record lookup because we've been doing exact same thing on a create for a while and works fine. No suggestions here then.
conradvillaconradvilla

Actually, I think it's unique to the use of RecordTypeId's in Dynamic Choices, because I've updated existing records after a lookup and have successfully created records many times.  When it comes to narrowing down a Dynamic Choice to a specific record type, I've always had to hardcode the "short" ID for the Record Type and unfortunately you cannot filter your recordtype in a Dynamic Choice using the Developer Name by putting in something like RecordTypeID__r.DeveloperName == 'Client'

conradvillaconradvilla

OK, so the only way we were able to get around the issue, was to write an Apex Plug-in

 

global class flowGetRTId implements Process.Plugin { 

// The main method to be implemented. The Flow calls this at runtime.
global Process.PluginResult invoke(Process.PluginRequest request) { 
        
        String theObject = (String) request.inputParameters.get('Object');
        String theName = (String) request.inputParameters.get('Name');

        // Using the Object and Name provided attempt to find the Record Type
        List<RecordType> theList = [Select Id, DeveloperName, SObjectType from RecordType Where DeveloperName =:theName And SObjectType =:theObject LIMIT 1];
        
        String truncatedId = null;
        if(!theList.isEmpty()){
            truncatedId = String.valueOf(theList[0].Id).left(15);
        }
        // return to Flow
        Map<String,Object> result = new Map<String,Object>(); 
        result.put('RTId',truncatedId);
        return new Process.PluginResult(result); 
    } 

    // Returns the describe information for the interface
    global Process.PluginDescribeResult describe() { 
        Process.PluginDescribeResult result = new Process.PluginDescribeResult(); 
        result.Name = 'flowGetRTId';
        result.inputParameters = new 
           List<Process.PluginDescribeResult.InputParameter>{
               new Process.PluginDescribeResult.InputParameter('Object', Process.PluginDescribeResult.ParameterType.STRING, true),
               new Process.PluginDescribeResult.InputParameter('Name', Process.PluginDescribeResult.ParameterType.STRING, true)   
            };
        result.outputParameters = new 
           List<Process.PluginDescribeResult.OutputParameter>{
               new Process.PluginDescribeResult.OutputParameter('RTId', Process.PluginDescribeResult.ParameterType.STRING)
           }; 
        return result; 
    }

    static testmethod void TestflowGetRTId() {
        flowGetRTId plugin = new flowGetRTId();
        
        // return the Describe results
        Process.PluginDescribeResult thisDescribe = plugin.describe();
        
        // Create default values for each of the expected params
        Map<String,Object> inputParams = new Map<String,Object>();
        
        // As we cannot insert Record Types we must assume that there is a Client Record Type for Accounts
        InputParams.put('Object', 'Account');
        InputParams.put('Name', 'Client');

        Process.PluginRequest request = new Process.PluginRequest(inputParams);  
        
        // Run the plugin
        Process.PluginResult result;
        result = plugin.invoke(request);
        
        // Since we can not insert Record Types testing to verify whether the ID returned is not necessarily repeatable.
        // Therefore we are commenting out the following test
        // System.assertEquals('012700000005bVu',result.outputParameters.get('RTId'));
    } 
    
    static testmethod void testFlowGetRTId_NoResults() {
        flowGetRTId plugin = new flowGetRTId();
        Map<String,Object> inputParams = new Map<String,Object>();
    // Test 1
        // Create params which should not return any Record Types, invalid Object names or missing values
        InputParams.put('Object', 'TestObject1234567890');
        InputParams.put('Name', '');
        
        // Run the plugin
        Process.PluginRequest request = new Process.PluginRequest(inputParams);  
        Process.PluginResult result;
        result = plugin.invoke(request);

        // Verify that NULL is returned
        System.assertEquals(null,result.outputParameters.get('RTId'));
    // Test 2
        // Create params which should not return any Record Types, invalid Object names or missing values
        InputParams.put('Object', 'Account');
        InputParams.put('Name', 'NotARealRecordType');
        
        // Run the plugin
        request = new Process.PluginRequest(inputParams);  
        result = plugin.invoke(request);

        // Verify that NULL is returned
        System.assertEquals(null,result.outputParameters.get('RTId'));
    // Test 3
        // Create params which should not return any Record Types, invalid Object names or missing values
        InputParams.put('Object', 'Account');
        InputParams.put('Name', '');
        
        // Run the plugin
        request = new Process.PluginRequest(inputParams);  
        result = plugin.invoke(request);

        // Verify that NULL is returned
        System.assertEquals(null,result.outputParameters.get('RTId'));
    // Test 4
        // Create params which should not return any Record Types, invalid Object names or missing values
        InputParams.put('Object', '');
        InputParams.put('Name', 'Client');
        
        // Run the plugin
        request = new Process.PluginRequest(inputParams);  
        result = plugin.invoke(request);

        // Verify that NULL is returned
        System.assertEquals(null,result.outputParameters.get('RTId'));

 

This was selected as the best answer
Jeff BloomerJeff Bloomer

I know that this has been marked as SOLVED, but did anyone consider just passing the RecordTypeId into the flow in the URL used to launch it?

DarrellDDarrellD

He's talking about getting the Ids and doing the lookup inside the Flow. The record type isn't known when person launches the Flow. He wants them to pick it when inside the Flow.