Flow Apex Action – return multiple elements?

I have a flow and due to the complexity of the logic, I moved some of the logic into apex (However I need to use minimum apex).

I’m looping through some records and finding related records (I need only one to be added to the list). And if there are no records found, I’m adding the Id to a list of Strings (Later I need it to send an email from the flow).

But how can I pass the list of Strings back to the flow in addition to the list of records I’m returning? Is there a way to set flow variables from apex instead of returning?

    @InvocableMethod
    public static List<List<Maintenance__c>> getMaintenanceRecordsToBeCloned(List<List<Maintenance__c>> mains){

        List<Maintenance__c> maintenances = mains.get(0);
        List<Maintenance__c> listTobeCloned = new List<Maintenance__c>();
        List<String> missingRecords = new List<String>();

        Property_Agreement__c[] props = [SELECT Name, Id FROM Property_Agreement__c WHERE Active_c=True];

        //doing the following to get only one Maintenance record per Agreement
        for(Property_Agreement__c prop : props){
            Boolean isRecordFound = false;
            for(Maintenance__c main: maintenances){
                if(main.Property_Agreement__c == prop.Id){
                    listTobeCloned.add(main);
                    isRecordFound = true;
                    break;
                }
            }
            if(!isRecordFound){

                missingRecords.add(prop.Id);
            }
        }
        List<List<Maintenance__c>> result = new List<List<Maintenance__c>>();
        result.add(listTobeCloned);

        //is there a way to return missingRecords too?
        return result;
    }

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

You use InvocableVariable annotations in a custom class. A demonstration of this is included in the documentation.

global class ConvertLeadAction {
  @InvocableMethod(label='Convert Leads')
  global static List<ConvertLeadActionResult> convertLeads(List<ConvertLeadActionRequest> requests) {
    List<ConvertLeadActionResult> results = new List<ConvertLeadActionResult>();
    for (ConvertLeadActionRequest request : requests) {
      results.add(convertLead(request));
    }
    return results;
  }

  public static ConvertLeadActionResult convertLead(ConvertLeadActionRequest request) {
    Database.LeadConvert lc = new Database.LeadConvert();
    lc.setLeadId(request.leadId);
    lc.setConvertedStatus(request.convertedStatus);

    if (request.accountId != null) {
        lc.setAccountId(request.accountId);
    }

    if (request.contactId != null) {
      lc.setContactId(request.contactId);
    }

    if (request.overWriteLeadSource != null && request.overWriteLeadSource) {
      lc.setOverwriteLeadSource(request.overWriteLeadSource);
    }

    if (request.createOpportunity != null && !request.createOpportunity) {
      lc.setDoNotCreateOpportunity(!request.createOpportunity);
    }

    if (request.opportunityName != null) {
      lc.setOpportunityName(request.opportunityName);
    }

    if (request.ownerId != null) {
      lc.setOwnerId(request.ownerId);
    }

    if (request.sendEmailToOwner != null && request.sendEmailToOwner) {
      lc.setSendNotificationEmail(request.sendEmailToOwner);
    }

    Database.LeadConvertResult lcr = Database.convertLead(lc, true);
    if (lcr.isSuccess()) {
      ConvertLeadActionResult result = new ConvertLeadActionResult();
      result.accountId = lcr.getAccountId();
      result.contactId = lcr.getContactId();
      result.opportunityId = lcr.getOpportunityId();
      return result;
    } else {
      throw new ConvertLeadActionException(lcr.getErrors()[0].getMessage());
    }
  }

  global class ConvertLeadActionRequest {
    @InvocableVariable(required=true)
    global ID leadId;

    @InvocableVariable(required=true)
    global String convertedStatus;

    @InvocableVariable
    global ID accountId;

    @InvocableVariable
    global ID contactId;

    @InvocableVariable
    global Boolean overWriteLeadSource;

    @InvocableVariable
    global Boolean createOpportunity;

    @InvocableVariable
    global String opportunityName;

    @InvocableVariable
    global ID ownerId;

    @InvocableVariable
    global Boolean sendEmailToOwner;
  }

  global class ConvertLeadActionResult {
    @InvocableVariable
    global ID accountId;

    @InvocableVariable
    global ID contactId;

    @InvocableVariable
    global ID opportunityId;
  }

  class ConvertLeadActionException extends Exception {}
}

Notice how you can set some to be required, or not, and you can choose multiple types; each can be input or output values, and will be exposed to the flow. Each corresponding index in the input should have a corresponding output in the return value.

In your example, it would look like:

@InvocableMethod
public static List<CloneMaintenanceResult> getMaintenanceRecordsToBeCloned(List<CloneMaintenanceRequest> mains){

public class CloneMaintenanceResult {
  @InvocableVariable Maintenance__c[] records;
  ...
}
public class CloneMaintenanceRequest {
  @InvocableVariable Maintenance__c[] records;
  ...
}


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x