Autlolaunched Flow bulkification prevents correct update

bulkificationprocess-buildervisual-workflow

I have built a autolaunched flow that is triggered by a process builder related to a custom object. The custom Object is a child object to Account.

The use case I am trying to solve is that on the account a custom custom text field Summary__c should be populated with a text value depending on a custom field Type__c on the custom Object.

Account (field Summary__c)

CustomObject__c (field Type__c)

The process is as follows:

  1. A record of CustomObject__c with Type__c "ValueA" is inserted
  2. the process builder on CustomObject__c registers the insert and calls the autolaunched flow
  3. the autolaunched flow checks if the related account has already "ValueA" in the field Summary__c

4.a if yes nothing is done

4.b if no "ValueA" is written into Summary__c
5. the autolaunched flow updates the account

If a CustomObject__c record with "ValueB" is created later, then "ValueB" should be added to the Summary__c field on the account so it would say "ValueA ValueB"

The problem

The process works fine for single record DMLs but if I insert a list of CustomObject__c records the autolaunched flow bulkification leads to a problem in step 3 + 4.

So if I insert a list of two CustomObject__c records, one with Type__c="ValueA" and one with Type__c="ValueB" the following happens:

The GetRecord Element that queries the accounts with the Summary__c field is bulkified, so the flow waits till all interviews (means both records) reach that element and then executes a combined query. That means for both records the Account.Summary__c field is empty.
The flow continues and both write their value into the Summary__c field.
The result is that record A writes "ValueA" into the account and record B writes "ValueB" and the last update on the account wins.

So the account is left with "ValueB" when the desired output is "ValueA ValueB".

Is there anything we can do that mass scenarios are recognised and instead of updating the account twice, the value can be combined before the update? This should of course not just work for two records.

Best Answer

By definition, each of the Custom_Object__c starts a new flow interview which has no knowledge of any other Flow Interview

Yet, since they share a common parent, the last Flow Interview wins in terms of updating a concatenated field on Account (the parent)

This problem can't be solved with Flow; you need to use an Apex trigger on Custom_Object__c which has available to it Trigger.new which will have all Custom_Object__c for that transaction (in 200 rec chunks).

You can take Trigger.new and pivot it on Account__c using a for loop and then construct the concatenated result. Something like this

Map<Id, Custom_Object__c[]> custObjsByAccountID = new Map<Id, Custom_Object__c[]> ();
for (Custom_Object__c custObj : Trigger.new) {
   if (custObj.Account__c == null) {continue;}
   if (!custObjsByAccountID.containsKey(custObj.Account__c) {
       custObjsByAccountID.put(custObj.Account__c,new List<Custom_Object__c> ();
   }
   custObjsByAccountID.get(custObj.Account__c).add(custObj);
}

// at this point, you can loop through the keySet of the map and construct the updated accounts

Account[] accounts = new List<Account>();
for (Id acctId : custObjsByAccountID.keySet()) {
  Account a = new Account(Id = acctId,  Summary__c = '');
  for (Custom_Object__c custObj: custObjsByAccountID.get(acctId)) {
     // do work to append to a.Summary__c
  }
}
update accounts;