I’ve been so proud on myself the other day when I created this complex flow.
So disappointed when it crashed in production due to Apex CPU limits.
Double proud when I redid it into a combination of flow and Apex.
Let’s find out what and why, but before I’ll tell you my story watch this awesome presentation, which will present you the solution and how consultants and developers can work together to deliver awesome-ness.
The Challenge
My customer wants to generate invoices in Salesforce on monthly basis, they will manually go through the list of opportunities in the month and select opportunities which can be invoiced.
Each invoice can contain multiple opportunities, meaning there is just one invoice per client per month.
If that looks easy (it kind of is), each OpportunityLineItem can be invoiced to different client, in such case the opportunity isn’t linked to the invoice, only the lines.
The Process
The flow was kind of complex.
- get all opportunities which are completed but hasn’t been invoiced yet;
- present them in screen flow data table so the user can select those to be invoiced;
- go throught the selected opportunities and collect unique accounts (sadly we cannot do aggregated query);
- go through line items for the selected opportunities, if they are invoiced to account and collect unique accounts from here;
- get invoices which has been created for this months already – as the user can select maximum of 200 opportunities (due to data table limits) it might happen that invoice for this account already has been created;
- create an invoice for each unique account;
- go through the selected opportunities and assign the created invoice;
- go through the line items for selected opportunities and assign the created invoice;
- success!
What I found out during the process is how limiting it is, that you cannot use something developers call Maps. How limiting it is to loop through opportunities to collect unique accounts as we cannot do so-called aggregated queries in flow. As we cannot use Maps we need to use the Filter element in the flow to filter that one invoice. That it is super slow to loop through all the records. The fact that there isn’t the 2000 process elements limit anymore is cool, but it will drop on CPU time anyway. If you want to get around CPU time you can show screen after some number of iterations as it will reset the limits, but it is annoying to user.
The Solution
You know the solution because you watched the video – it is called Invocable actions. In my case it meant that I went from the flow on the left handside, which took be roughly two days to create and redo, to the combination of simple flow and simple Apex (ok, probably not the best code) on right handside, which I put together in roughly an hour.
Learning
It isn’t that hard to write the invocable action, but there are a few surprising moments (which can be seen on the picture above as well).
- the method parameter isn’t List<Id> as one would expect when passing multiple records, but List<List<Id>> where the outer list has just one value;
- suprisingly you cannot pass the list of selected records directly from data table, I had to loop through them in the flow and add them into another variable, which I was able to pass.
Go for it!
Yes, my dear consultant, there is no reason to be proud on yourself that you created something super complex with loop inside a loop inside a loop. Speak with your friendly developer, who can easily do aggregations, sub-queries, use Map to quickly go through records and all of that in a fraction of time it would take to you. And it will have better readability and at the end less of technological debt.
This is the way to go. And second time you’ll find out you can write it on your own. Because you are the best!
Napiš komentář, díky!