Salesforce Flows

Lets discusss on Calling Apex method from Flow in a very detailed manner.

As I couldn’t find any blog or post on Flows that calls apex method passing a parameter, sending the result using Apex-Defined Data Type and generic way of writing @InvocableMethod

Some important points to be noted down regaridng @InvocableMethod

If your returning a single record from apex Invocable methord to Flow,
Retun type must be a List type.

Example 1:

@InvocableMethod(Label='Get Count')
public static List<Integer> getCount(List<String> requestList) {
   List<Integer> result = new List<Integer>();

   try{
         List<Sobject> records = Database.query(requestList[0]);
         result.add(records.size());
         return result;
   }
   catch(Exception e){
       result.add(0);
     return result;
   }
}

Example 2:

@InvocableMethod(label = 'Fetch Account Record' description ='This will return single Account record' category ='Account')
public static List< Account > FetchSingleRecordFromAccount(){
 return [Select Id, Name, BillingPostalCode From Account Limit 1];
} 

If your returning a List of record from apex Invocable methord to Flow, Retun type must be a List of List type.

Example 1:

@InvocableMethod
   public static List<list<string>> MultiSelectPickListToListOfValues(List<string> values) {
   
      if(!(values.isEmpty())){
          
          string tempStr = values[0];
                      
          List<String> lstnew = tempStr.split(';');
                     
          list<list<string>> finalLst = new list<list<string>>();
          finalLst.add(lstnew);

          
          return finalLst;
      }
      else return null;
   }

Example 2:


@InvocableMethod(label = 'Fetch Account Records' description ='This will return multiple Account records' category ='Account')

public static List < List< Account > > FetchRecordsFromAccount(){
 
return [Select Id, Name, BillingPostalCode From Account Limit 10];

} 

Now Lets Jump into our actual Concept which i found more intresting

What is Apex-Defined Data Type:
  With the Apex-defined data type, flows can manipulate the kinds of complex data objects that are typically returned from calls to web services. Create Apex-defined variables in flows and directly process JSON returned from web calls.

To Send our wrapper class data to Salesforce Flow from Apex we can use this concept.

Wrapper class Variables must declear as @AuraEnabled @InvocableVariable

Example: Iam tryingh to tweak the Code, so please bear with me example may not be appropriate, as the purpuse of the code is different.
Acutally a record will be created in salesforce by some ERP system as webservice call,
by mistake user creates a record(s) manually with the same set of data with Defferent recordType. so our intension is to identify those records and to merge and delete the ERP record in Salesforce. This is the actaul concept, dont worry i am not going to code about to find the duplicate records etc.

We are sending the records to Screen Fow as Radiobuttons data
My intension is just how we can use Apex-defined types only.
Please ignore Variable and function naming convention as i already told i am just tweaking the actual code and removed the unnecessary complexity in the code to make it simple to understand the concept and usge of Apex-Defined types.

Apex-Defined Data Type

public class ContactWrapper{
        
 @AuraEnabled @InvocableVariable(Label='unique ProspectKey' Description = 'This is the Unique record indentifier.')
       public  String uniqueProspectKey;
      
 @AuraEnabled @InvocableVariable(Label='ContactId' Description = 'Contact Record Id')
        public  String Id;
      
    }

} 
public class DuplicateCheckerProspectAccounts {
	
    @InvocableMethod(Label = 'Duplicate CustomerRecord' category = 'Dupchecker')
    public static List < List < ProspectWrapper > > FetchPossibleDuplicateRecords(List < Account > customerAccountList) {

        Boolean isPersonAccount;
        List < List < ProspectWrapper > > allUniqueProspectAccountsList = new List < List < ProspectWrapper > > ();
        List < ProspectWrapper > allUniqueProspectAccounts = new List < ProspectWrapper > ();
        Account customerAccount = customerAccountList[0];
        .
        .
        .
        isPersonAccount = (Boolean) customerAccount.get('IsPersonAccount');
        uniqueCustomerKey = customerAccount.BillingPostalCode + '..some unique combinations from record';

        List < Account > prospectAccounts = [SELECT Id, Name, .....FROM Account WHERE.....];                    

        if (ProspectAccounts.size() > 0) {
            salesforceBaseUrl = URL.getSalesforceBaseUrl().toExternalForm() + '/';
            for (Account acc: ProspectAccounts) {
                uniqueProspectKey = acc.BillingPostalCode + '..some unique combinations from record';
                if (uniqueCustomerKey == uniqueProspectKey) {
                    ProspectWrapper uniqueRec = new ProspectWrapper();
                    urlId = salesforceBaseUrl + acc.Id;
                    uniqueRec.uniqueProspectKey = '<html><a href="' + urlId + '" style ="color:black;text-decoration: none;">' + String.valueOf(acc.Name) + '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <b> Created Date: </b>' + String.valueOf(acc.CreatedDate) + '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>Created By:</b> ' + acc.CreatedBy.Name + '</a></html>';
                    uniqueRec.Id = acc.Id;
                    allUniqueProspectAccounts.add(uniqueRec);
                }
            }
        }
        allUniqueProspectAccountsList.add(allUniqueProspectAccounts);
        return allUniqueProspectAccountsList;
    }
    public class ProspectWrapper {

        @AuraEnabled @InvocableVariable(Label = 'unique ProspectKey'
            Description = 'This is the Unique record indentifier.')
        public String uniqueProspectKey;

        @AuraEnabled @InvocableVariable(Label = 'ProspectId'
            Description = 'Prospect Account Record Id')
        public String Id;

    }
}

The Screen Flow Variable will look like this.

Apex Defined Type

Leave a comment