Skip to main content

I am creating an Apex action according to the info described here, using custom defined objects for passing in the request and out the result.

 

Having defined those objects, in flow, I am able to create an apex-defined single-value variable for the request object type as well as a collection of that object type.

 

However, when I try to invoke the apex action, it only allows me to enter the single object variable and not the collection one.

 

My understanding is that the Apex action is expecting a List of these custom objects.  So I initially defined the method for this action as follows:

 

global class FindOrCreateContacts {

@InvocableMethod(label='Find or Create Contacts' category='Contact')

global static List<FOCCActionResult> GetIDs(List<FOCCActionRequest>> requests) {

...

With the custom object defined as:

global class FOCCActionRequest {

@InvocableVariable(required=true) @AuraEnabled

global String email;

@InvocableVariable(required=true) @AuraEnabled

global String lastname;

@InvocableVariable @AuraEnabled

global String firstname;

@InvocableVariable @AuraEnabled

global String country;

}

This is how it is shown in the example code on that page.  However, when I tried to invoke the action from flow, it was requesting the individual variables of the class (email, lastname, firstname, etc.) instead of an instance of that class.

 

OK, so I changed the method signature to:

global class FindOrCreateContacts {

@InvocableMethod(label='Find or Create Contacts' category='Contact')

global static List<List<FOCCActionResult>> GetIDs(List<List<FOCCActionRequest>> requests) {

Now in Flow, it asks for an instance of requests, but it will only allow me to select a single instance variable but not a collection of those objects.

 

I tried adding another layer of List< to the method signature, but that was not accepted.

 

Can anyone tell me what I'm doing wrong?    Thanks!

 

#apex #Flow #Invocable Actions

3 个回答
  1. 2023年3月2日 18:14

    Here's the full source of this (I hope!) useful function, in case anyone is interested.

     

    global class FindOrCreateContacts {

    @InvocableMethod(label='Find or Create Contacts' category='Contact' description='Called by flow Upload CNVC CSV to return a list of all transactions passed to it with the ContactIDs and AccountIDs added')

    // This method makes use of a custom object created in the host system called "CNVC_Import__c".

    // This allows us to pass and manipulate data as SObjects for convenience. However, we never write them to the database.

    global static List<List<CNVC_Import__c>> GetIDs(List<List<CNVC_Import__c>> requests) {

    // Because Flow expects lists of lists as input and output, create "results" variable and then create the first list inside the first list

    List<List<CNVC_Import__c>> results = new List<List<CNVC_Import__c>>();

    results.add(new List<CNVC_Import__c>());

    // These are sets to ensure uniqueness so we only create users once if they appear more than once

    Set<String> allEmails = new Set<String>();

    Set<String> allNewEmails = new Set<String>();

    Set<String> foundEmails = new Set<String>();

    // Used as lookup tables to link emails to Contact and Account IDs

    Map<String,ID> contactIDs = new Map<String,ID>();

    Map<String,ID> accountIDs = new Map<String,ID>();

    system.debug('Input' + requests);

    // Extract all emails from input records into a set which will be used to look them all up at once

    // We're referencing "requests[0]" because it was passed as a list of lists.

    for (CNVC_Import__c request : requests[0]) {

    allEmails.add(request.Email__c);

    }

    system.debug('allEmails set:' + allEmails);

    // Find any contact records that have an email from the request list

    List<Contact> existingContacts = [SELECT Id, FirstName, LastName, Country__c ,AccountId, Email FROM Contact where Email in :allEmails];

    system.debug('Existing Contacts' + existingContacts);

    // Add existing contact IDs to contactIDs and AccountIDs lookup maps

    for(Contact contact : existingContacts){

    contactIDs.put(contact.email, contact.Id);

    accountIDs.put(contact.email, contact.AccountId);

    foundEmails.add(contact.Email);

    }

    //system.debug('FoundEmails after adding existing' + foundEmails);

    //system.debug('Results after adding existing' + results[0]);

    // Now loop through request records and prepare to create any emails not already found

    List<Contact> newContacts = new List<Contact>();

    for (CNVC_Import__c request : requests[0]){

    if (foundEmails.contains(request.Email__c)) {

    system.debug('Was Found: ' + request);

    // Do nothing - Contact already exists

    } else {

    system.debug('Adding New: ' + request);

    newContacts.add(new Contact (LastName = request.Lastname__c,

    FirstName = request.Firstname__c,

    Email = request.Email__c,

    Country__c = request.Country__c));

    // Add to list of IDs for later query to get AccountIDs

    allNewEmails.add(request.Email__c);

    }

    }

    system.debug('Newcontacts before insert' + newContacts);

    // Now insert list of contacts

    try {

    insert newContacts;

    } catch(DMLException e) {

    return null;

    }

    //system.debug('Newcontacts after insert' + newContacts);

    //system.debug('Results after insert' + results);

    // Now retrieve those same new contacts. We have to do this so we can get access to the accountIDs.

    // Because we are on NPSP with house accounts, accounts get created automatically as Contacts get created,

    // but their IDs are not available unless you query for those contacts.

    List<Contact> retrievedNewContacts = [SELECT Id, AccountId, Email, Firstname, Lastname, Country__c FROM Contact where Email in :allNewEmails];

    //Add new contacts IDs to Maps for ContactIDs and AccountIDs

    for(Contact contact : retrievedNewContacts){

    contactIDs.put(contact.email, contact.Id);

    accountIDs.put(contact.email, contact.AccountId);

    }

    // Now we add any newly-created contact info into the results list of Sobjects

    For (CNVC_Import__c trans : requests[0]) {

    results[0].add(new CNVC_Import__c(

    Firstname__c = trans.Firstname__c,

    Lastname__c = trans.Lastname__c,

    Country__c = trans.Country__c,

    Email__c = trans.Email__c,

    Contact_ID__c = contactIDs.get(trans.Email__c),

    Account_ID__c = accountIDs.get(trans.Email__c),

    Amount__c = trans.Amount__c,

    Date__c = trans.Date__c,

    Existing_User__c = foundEmails.contains(trans.Email__c)));

    }

    system.debug('Final Results' + results);

    return results;

    }

    public virtual class CNVCException extends Exception {}

    }

0/9000