Andy in the Cloud

From BBC Basic to Force.com and beyond…


79 Comments

Declarative Rollup Tool Summer Release!

Over the course of the last couple of weeks, i have been focusing my community time on release v2.4 of the DLRS tool. Specifically focusing on some much requested features driven by the community in the the Chatter group.

So lets get stuck in…

Rollup Scheduler Improvements

The ability to run a full (or partial with criteria) recalculate of a rollup on a daily schedule has been in the tool for a few releases now. However up until now the only option was to run it at 2am everyday. It is now possible to change this with this new UI, its a bit raw and basic, but for now it should at least give some more flexibility.

RollupSchedule.png

Support for Merging Accounts, Contacts and Leads

The platform has some special handling for merging Accounts, Contacts and Leads. Especially when it comes to when Apex Triggers are invoked. Basically if your parent object is one of these objects, prior versions of the tool had no awareness of this operation, so rollups would not recalculate. If you are using Realtime or Schedule calculation modes on your rollups. Since the platform does not fire Apex Triggers for child records reparented as a result of a merge.

With this release there are two things you can do to fix this. First when you click the Manage Child Trigger button, you get a new checkbox option to control deployment of an additional Apex Trigger on the parent object. If your upgrading you will need to click Remove then Deploy again, to see this.

ParentTrigger.png

IMPORTANT NOTE: If you don’t feel merge operations are an issue for your use cases you can deselect this option and cut down on the number of triggers deployed. Also if it is only the rollup child object that supports merging, there is no need to deploy any additional triggers and the tool does not show the above checkbox option.

Secondly you need to setup the RollupJob as an Apex Scheduled job (under Setup > Apex Classes), even if you don’t have any Schedule Mode rollups. This is due to the fact that due to a platform restriction, the tool cannot recalculate rollups realtime during a merge operation. So it can only record that they need to be recalculated. It does this via the tools scheduled mode infrastructure, by automatically adding records to the Lookup Rollup Summary Schedule Items object. Note that you don’t need to change your rollups from Realtime to Scheduled mode for this to work, only schedule the job.

Support for Archived / Deleted Records via the All Rows Setting

Salesforce archives Tasks and Events after a while. If you have rollups over these child objects you can enable the Aggregate All Rows checkbox. This will ensure your rollups remain accurate even if some records have been archived. Note this also will apply to records in the recycle bin. For upgrades (if your not using the Manage Lookup Rollup Summaries tab), you will need to add this field to your layout to see it.

AllRows.png

Row Limit for Concatenate and Last Rollup Operations

If your using the Last or Concatenate operations, you can define a limit as to how many child records are actually considered when calculating the rollup. This is useful if your using Concatenate into a fix length field for example. When upgrading you need to add the new Row Limit field to your layout if your not using the swanky new Manage Lookup Rollup Summaries tab.

RowLimit.png

Improved House Keeping for Scheduled Mode

If your are using rollups with their Calculation Mode set to Scheduled. The tool records parent rollup records to be later recalculated by the RollupJob Apex Scheduled job. In past releases if through merge or other operation the parent record was deleted before the next scheduled run. Then records would sit in limbo in the Lookup Rollup Summary Schedule Items object, being processed and erroring over and over. These will now be cleared out and there is no upgrade actions you need to take for this.

Summary

Thanks for everyones support for this tool, i hope these changes help you go further with clicks not code! Though as reminder please keep in mind the best practices and restrictions listed in the README. If you have any questions you can either post comments on this blog or use the Chatter Group. The Chatter Group is a great place to get your query seen by a broader group of people who are also diligently supporting the tool as well!

You can find releases of the tool here.


2 Comments

Disabling Trigger Events in Apex Enterprise Patterns

Iautobat.jpeg‘m proud to host my first guest bloggerChris Mail or Autobat as he is known on GitHub. Take it away Chris….

How to put the safety on…

Being an architect in a professional services organisation is a funny game. Each project is either a shiny new Salesforce instance without a fingerprint on it or an unknown vault of code and configuration that we must navigate through.

I have been using the fflib pattern now for some time, and more of our teams are adopting it for our programs of work. My latest addition is something that an architect might wonder why we need; the ability to turn off triggers via a simple interface on all domains.

In an ever growing complex environment, perhaps multiple projects over time delivering iterative enhancements I was noticing a common piece of code being developed within the Domain layer. It looked something along the lines of this:

public override void onAfterInsert()
{
    // if this is set we are already in a loop and want to exit!
    if(bProhibitAfterInsertTrigger)
    {
        return;
    }
    // down here we do something, maybe insert an Account!
}

While small and inconspicuous it allowed our code base to become inconsistent as there was no control over the exposure of these controlling flags and worse, we were repeating ourselves in every domain!

The solution was simple, a fluent style API within fflib_SObjectDomain. Any code can now simply set the control flags for any domain class:

fflib_SObjectDomain.getTriggerEvent(YourDomain.class).disableAll(); // dont fire anything
fflib_SObjectDomain.getTriggerEvent(YourDomain.class).disableAllBefore();
fflib_SObjectDomain.getTriggerEvent(YourDomain.class).disableAllAfter();

fflib_SObjectDomain.getTriggerEvent(YourDomain.class).disableBeforeInsert();
fflib_SObjectDomain.getTriggerEvent(YourDomain.class).disableBeforeUpdate();
fflib_SObjectDomain.getTriggerEvent(YourDomain.class).disableBeforeDelete();

fflib_SObjectDomain.getTriggerEvent(YourDomain.class).disableAfterInsert();
fflib_SObjectDomain.getTriggerEvent(YourDomain.class).disableAfterUpdate();
fflib_SObjectDomain.getTriggerEvent(YourDomain.class).disableAfterDelete();
fflib_SObjectDomain.getTriggerEvent(YourDomain.class).disableAfterUndelete();

To enable, just call the inverse e.g. .enableAfterInsert(); etc.

While not every code base will need to use these flags, they allow you to control quickly and easily your trigger execution with a single line of code that all your development team can reuse and follow.


14 Comments

GitHub Salesforce Deploy Tool Lightning Edition

A recent discussion on Twitter around sharing Salesforce configuration between admins has motivated me to revisit this tool. Before getting into anything major (watch this space). I decided to get back into the tools code by addressing a few outstanding maintenance tasks, enhancements and bug fixes, as well as treating it to a face lift!

LightningGitHubSFDeploy.png

As some of you may have noticed the tool has now adopted the Salesforce Lightning Design System look and feel. This new version is not just cosmetic, its also addressed some key enhancements and bug fixes…

LightningGitHubSFDeploy2.png

In keeping with the Lightning principles, this release makes the Deploy to Salesforce button (example shown below), even easier to place in your repository README files with less configuration required. The button will now automatically detect the GitHub repository. Which is useful if you Fork a repository into your own account or rename it, you no longer need to change the README file. The button code is now also smaller.

LightningGitHubSFDeployButton.png

IMPORTANT NOTE: This only works if your placing the button code in a GitHub README file. If your planning on using the button on a blog, article or wiki etc tick Use Specified Owner and Repository checkbox to have the specified repository details encoded into the button code as before.

This release has now also addressed issues preventing use with repositories that have Reports or Lightning Components in them. So you can now use the tool to deploy your favourite open source Lightning Components!

Finally if you have any private repositories, an improvement around the error handling in this area has also been made. Thanks to some great code contributions from Moti Korets and  Nathan Kramer for the whole GitHub private repository support! Thanks guys!

 

 


13 Comments

Rollups and Cross Object Formula Fields

I’m constantly amazed at the number of varied use cases folks in the Chatter Group are applying to the Declarative Lookup Rollup Summary tool these days. This short blog highlights a particular use case that seems to be on the increase. To resolve it i reached out for additional help in the solution from Process Builder, this is the story…

Background: What causes a Rollup to recalculate?

The default behaviour of the rollup tool is to look for changes to the field your rolling up on, the one specified in the Field to Aggregate field. In addition you can list other fields for it to look at via the Relationship Criteria Fields field, which as the name suggests is also important information if you’ve used rollup criteria. However its also important if the field your rolling up on is a Formula field. In the case of formula field rollups the platform doesn’t inform the tools Apex Trigger of changes to these. So it cannot directly monitor such fields and to resolve this must instead be told explicitly about the fields that are referenced by the formula expression. So far so good…

Challenge: Rollups over Cross Object Formulas?

A challenge however arises if you’re wanting to do a realtime rollup based on a formula field that references fields from a related record, a cross object formula! In this case how does the rollup tool know when changes are made to related records?

One solution to this is to switch to schedule mode by clicking the Schedule Calculate button on the rollup. For realtime rollups, its potentially feasible to enhance the tool to deploy triggers to related objects and bubble up knowledge of field changes to the cause a recalculate of the rollup on the child object… However before we resort to more code (even in the tool) lets see what we can do with the declarative tools we have already today…

Example Use Case

The following schema diagram shows a simplified mockup of a such a challenge i helped a community member out with in the tools Chatter Group.

FormulaRollupUseCase.png

Here is the scenario assumptions and break down…

  • For whatever existing reasons the above is NOT a Master Detail relationship
  • Rollup needed is to Sum the Quote Line Item > Amount into the Quote > Total field.
  • The Quote Line Item > Amount field is a Formula field, which is a cross object formula pointing to the related Widget > Total field.
  • The Widget > Total field is itself a Formula field, in this simplified case adding up the values of Widget > A + Widget > B + Widget > C.
  • Whenever changes to the Widget > A, Widget > B or Widget > C fields are made we want the Quote > Total field to be recalculated.

Here’s the rollup summary definition between Quote and Quote Line Item

ForumlaRollupDLRS.png

While the above works if you use Calculate (one off full recalculate) or Schedule Calculate (daily full recalculate) buttons. Our issue arises in the general use of the Realtime mode. Since the tools triggers see nothing of the changes users make to the Widget fields above, realtime changes are not reflected on the Quote > Total rollup. This is due to the aforementioned reason, since we are using a cross object formula.

NOTE: The Calculate Mode pick list also has a Schedule option, this is a more focused background recalculate, only recalculating effected records since the last run, rather than Schedule Calculate button which is a full recalculate every night. So be aware if your using this mode that the problem and solution being described here also applies to Calculate Mode when set to Schedule as well. As it uses the same field monitoring approach to queue records up for scheduled recalculation.

If your fine without realtime rollups go ahead and use the Schedule Calculate button and at 2am each morning the Quote > Total amount will catchup with any changes made to the Widget fields that effected it, job done!

Solution: Shadow Fields and Process Builder

So when considering the solution, i did consider another rollup between the Widget and Quote Line Item to start to resolve this, thinking i could then put the result in field that the Quote Line Item > Quote  rollup would see change. However this was quickly proved a poor consideration as the relationship between Widget and Quote Line Item in this use case is the wrong way round, as Quote Line Item is the child in this case, doh! In other use cases, i have had success in using nested rollups to get more complex use cases to fly!

Shadow Field?

AmountShadowFieldEither way i knew i had to have some kind of physical field other than a Formula field on the Quote Line Item object to notify the rollup tool of a change that would trigger a recalculate of the Quote > Total. I called this field Amount (Shadow) in this case, i also left it off my layout.

NOTE: I’ve made the assumption here that for whatever reason the existing cross object Formula field has to stay for other reasons, if thats not a problem for you, simply recreate Quote Line Item > Amount as a physical field and as you read the rest of this blog consider this your shadow field.

I then changed my rollup definition to reference the Amount Shadow field instead.

ChangesToRollup

NOTE: If you managed to switch the field type of your Amount field from a Formula to a physical Number field as noted above you don’t need to do this of course.

Process Builder to update your Field to Aggregate

Next i turned to Process Builder to see if i could get it populate the above Amount (Shadow) field on Quote Line Item, as users made changes to Widget fields. Leveraging the child parent relationship between Quote Line Item and Widget. Here is the setup i used to complete the solution!

FormulaRollupProessBuilder1.png

FormulaRollupProessBuilder2.png

FormulaRollupProessBuilder3.png

Summary

Its worth noting that if the relationship between Quote Line Item and Quote was Master Detail, you can effectively now of course use standard platform Rollup Summary Fields without needing the rollup tool at all. You may think me bias here, but not at all, i’d much rather see a fully native solution any day!

Regardless if this use cases fits yours or not, hopefully this blog has given you some other useful inspiration for further rollup and Process Builder combo deals! Enjoy!


52 Comments

Visual Flow with List View and Related List Buttons

Last years blog Clicks not Code with Visual Flow Custom Buttons has continued to be quite well received, so i thought i would explore what more could be done and address a few questions that have come up since. This blog does make some assumptions that you are already familiar with the approach from my previous blog.

This time i want to focus on using Visual Flows with list Custom Buttons, such buttons can be placed on List View layouts and Related List sections on Detail layouts. Salesforce also provides a means for the user to select specific records to process. These buttons apply to both Salesforce Classic and Salesforce Lighting Experience.

AccountFlowListView

As before we are keeping in the spirit of Clicks not Code, well with a little bit of reusable Visualforce code. But don’t worry you can easily copy and paste to adapt with a few changes. Critically with this approach you don’t need to resort to JavaScript based Custom Buttons, which will no longer be supported in Lighting Experience.

Handling Record Lists from Custom Buttons

First things first, ensure you have created a SObjectCollection variable in your Flow and ensured its designated as Input. For this blog we are simply going to display a step in the UI for each selected record. Using the Loop and Screen elements. One thing to keep track of is the fields your referencing within the Flow, in this case i’m using Account Name and Annual Amount.

SelectedAccountsFlow

List View Custom Button Example

Lets get started with a Custom Button on the Account List View. When adding a List Custom Button you have two choices, do you want the user to be able to select records or not? If not, then your button will pass all the records in the List View (currently limited to 2000).

So if when creating your Custom Button you plan to select the Display Checkboxes (for Multi-Record Selection) option. Then create the following Visualforce page, changing the object name and list of fields accordingly. This will ensure selected records are passed to your Flow.

<apex:page standardController="Account" tabStyle="Account" recordSetVar="AllAccounts" >
    <!-- Add below each field you reference in your Flow -->    
    <apex:repeat value="{!AllAccounts}" var="row" rendered="false">
        {!row.Name}
        {!row.AnnualRevenue}
    </apex:repeat>
    <!-- Runs your Flow -->    
    <flow:interview name="SelectedAccounts" 
          finishLocation="{!URLFOR($Action.Account.Tab, $ObjectType.Account)}">
        <apex:param name="SelectedRows" value="{!Selected}"/>
    </flow:interview>
</apex:page>

IMPLEMENTATION NOTE: If you want to avoid bothering with changes between lines 3-6, simply re-query the records in the Flow using the Fast Lookup element. Thought it’s less efficient this way since your not leveraging the query made by Visualforce.

If you don’t want the ability for the users to select records and want all records, the main difference to the above is a change to the line 10, passing in the AllAccounts binding.

    <!-- Runs your Flow -->    
    <flow:interview name="SelectedAccounts" 
          finishLocation="{!URLFOR($Action.Account.Tab, $ObjectType.Account)}">
        <apex:param name="SelectedRows" value="{!AllAccounts}"/>
    </flow:interview>

Don’t forget to add your button to the List View layout, select some records and give it a try!

SelectedAccountRow

Related List Custom Button Example

In this case the Visualforce page is much the same, accept that of course your placing the associated button on the Layout of the parent object by editing the applicable related list section. The following example shows a button on the Opportunities related list on the Account object.

<apex:page standardController="Opportunity" tabStyle="Opportunity" recordSetVar="AllOpportunities">
    <!-- Add below each field you reference in your Flow -->
    <apex:repeat value="{!AllOpportunities}" var="row" rendered="false">
        {!row.Name}
        {!row.Amount}
    </apex:repeat>
    <!-- Runs your Flow -->
    <flow:interview name="SelectedOpportunities" 
          finishLocation="{!$CurrentPage.parameters.retURL}">
        <apex:param name="SelectedRows" value="{!Selected}"/>
    </flow:interview>    
</apex:page>

RelatedListFlowButton

IMPLEMENTATION NOTE: Note that the above Visualforce page code uses a URL parameter retURL, which is not available in Lighting Experience. It still works, but leaves the user on the finish page.

Summary

For more information on passing values to Flows using Visualforce check out the docs here. With the exception of the retURL hack above, i’m pleased to see support in Classic and Lighting Experience. Though the later, has yet to obtain support for providing the record selection support, so only the all records use case is available.

At present Visual Flow styling does not quite look at home either in Lightning Experience, which made me wonder about trying SLDS styling with Flow’s CSS customisation abilities (i will let everyone known how successful this is!)…

AccountFlowListViewLEX

FlowInLEX

Finally both these approaches will also work equally well with Automation Flows (aka Headless Flows), just in case, as with the example in my earlier blog you just want to do some kind of calculations without prompting the user.