Skip to content

Releases: jamessimone/apex-rollup

v1.2.1 - Grandparent Rollups (files/directories reconfigured)

19 Mar 14:08
a237f1e
Compare
Choose a tag to compare

Grandparent (Or Greater) Rollups

(#60 was just reconfiguring the files/folders of the project and #57 is still the canonical release in terms of changes between v1.2.0 and v1.2.1)

It's not all that uncommon, especially with custom objects, to get into the practice of rolling up values from one object merely so that another parent object can receive those rolled up values; that is to say, we occasionally use intermediate objects in order to roll values up from a grandchild record to a grandparent (and there's no need to stop there; it's totally possible to want to roll up values from great-grandchildren to the great-grandparent record, and so on). Rollup offers the never-before-seen functionality of skipping the intermediate records so that you can go directly to the ultimate parent object. This is supported through the invocable rollup actions, as well as through the CMDT-based rollup approach by filling out the optional field Grandparent Relationship Field Path:

Example grandparent rollup

In this example, there are four objects in scope:

  • ApplicationLog__c, which has a lookup field Application__c
  • Application__c, which has a lookup field ParentApplication__c
  • ParentApplication__c, which has a lookup field Account__c
  • Account, and the field we'd like to rollup to has the API name AnnualRevenue

Important things to note about grand(or greater)parent rollups:

  • super important all intermediate objects in the chain (so, in this example, Application__c, and ParentApplication__c) must also have the Rollup.runFromTrigger() snippet in those object's triggers (or the appropriate invocable built). This special caveat handles cases where the intermediate objects' lookup fields are updated; no big deal if the ultimate parent lookup hasn't changed, but big deal if the ultimate parent lookup has changed
  • if your CMDT/invocable is set up with a relationship that is not the immediate parent and you don't fill out the Grandparent Relationship Field Path, it simply won't work. The field path is required because it's common for objects to have more than one lookup field to the same object
  • if you are using Grandparent Relationship Field Path with a polymorphic standard field like Task.WhatId or Task.WhoId, you should also supply a SOQL Where Clause to ensure you are filtering the calculation items to only be related to one type of parent at a time. Note - at this time, the SOQL Where Clause only works on the fields present on the initial calculation items, and does not support cross-object filtering
  • grandparent rollups respect SOQL's map relationship-field hopping of 5 levels:

In each specified relationship, no more than five levels can be specified in a child-to-parent relationship. For example, Contact.Account.Owner.FirstName (three levels)

While the base architecture for retrieving grand(or greater)parent items has no technical limit on the number of relationship field hops that can be made, correctly re-triggering the rollup calculations after an intermediate object has been updated made it necessary to respect this limit (for now).

v1.2.0 - Grandparent Rollups (Original)

27 Mar 22:08
0cd4f62
Compare
Choose a tag to compare

Grandparent (Or Greater) Rollups

It's not all that uncommon, especially with custom objects, to get into the practice of rolling up values from one object merely so that another parent object can receive those rolled up values; that is to say, we occasionally use intermediate objects in order to roll values up from a grandchild record to a grandparent (and there's no need to stop there; it's totally possible to want to roll up values from great-grandchildren to the great-grandparent record, and so on). Rollup offers the never-before-seen functionality of skipping the intermediate records so that you can go directly to the ultimate parent object. This is supported through the invocable rollup actions, as well as through the CMDT-based rollup approach by filling out the optional field Grandparent Relationship Field Path:

Example grandparent rollup

In this example, there are four objects in scope:

  • ApplicationLog__c, which has a lookup field Application__c
  • Application__c, which has a lookup field ParentApplication__c
  • ParentApplication__c, which has a lookup field Account__c
  • Account, and the field we'd like to rollup to has the API name AnnualRevenue

Important things to note about grand(or greater)parent rollups:

  • super important all intermediate objects in the chain (so, in this example, Application__c, and ParentApplication__c) must also have the Rollup.runFromTrigger() snippet in those object's triggers (or the appropriate invocable built). This special caveat handles cases where the intermediate objects' lookup fields are updated; no big deal if the ultimate parent lookup hasn't changed, but big deal if the ultimate parent lookup has changed
  • if your CMDT/invocable is set up with a relationship that is not the immediate parent and you don't fill out the Grandparent Relationship Field Path, it simply won't work. The field path is required because it's common for objects to have more than one lookup field to the same object
  • if you are using Grandparent Relationship Field Path with a polymorphic standard field like Task.WhatId or Task.WhoId, you should also supply a SOQL Where Clause to ensure you are filtering the calculation items to only be related to one type of parent at a time. Note - at this time, the SOQL Where Clause only works on the fields present on the initial calculation items, and does not support cross-object filtering
  • grandparent rollups respect SOQL's map relationship-field hopping of 5 levels:

In each specified relationship, no more than five levels can be specified in a child-to-parent relationship. For example, Contact.Account.Owner.FirstName (three levels)

While the base architecture for retrieving grand(or greater)parent items has no technical limit on the number of relationship field hops that can be made, correctly re-triggering the rollup calculations after an intermediate object has been updated made it necessary to respect this limit (for now).

v1.1.11 - Trigger/metadata bugfixes

16 Mar 03:14
Compare
Choose a tag to compare
  • added negative test via feedback from @JimBTek to ensure no further trigger-based regressions, fixed cached metadata issue
  • updated build script

Update Documentation

11 Mar 17:00
Compare
Choose a tag to compare
  • better documentation to officially close out #53
  • added integration test for flow engine issue (when this test starts failing, the section of the Readme associated with using Get Records in a Record Triggered flow can be deleted 😇)

Proper CONCAT, CONCAT_DISTINCT support for parent multi-select fields

11 Mar 03:04
Compare
Choose a tag to compare
  • Fixes #53 by ensuring string-based lookups conform to the multi-select picklist shape for concat in particular
  • Fixed an issue with the build script that didn't always report test failures (most likely due to a breaking change in the CLI, as the build used to bomb out on test failure). We now explicitly check the test result status in case the exit code for the test command isn't returned to the shell correctly

Bugfixes for AVERAGE

09 Mar 22:32
Compare
Choose a tag to compare
  • Fixed a bug with AVERAGE where not all calc items were being applied to the denominator when a where clause had been passed
  • Fixed a bug with RollupEvaluator where "special" phrases ("in" / "not in") were being taken out of context when filtering SObjects

Easier imperative Apex, fix truncation on update

04 Mar 23:58
c893d38
Compare
Choose a tag to compare
  • Fix for #49 by enabling truncation on update
  • Fix for #48 by exposing runFromApex(List<SObject> records, TriggerOperation rollupContext) method - possible values for the rollupContext argument are:
  • TriggerOperation.AFTER_INSERT
  • TriggerOperation.AFTER_UDATE
  • TriggerOperation.BEFORE_DELETE
  • TriggerOperation.AFTER_UNDELETE

Stable For Custom Objects / Custom Fields

04 Mar 15:22
efa2591
Compare
Choose a tag to compare
  • Actual fix for #45 (support for custom objects)
  • Fixed issue where averages could blow up when a null value was present
  • Fixed a potential concat issue caused by trailing delimiters, added additional integration tests.
  • Fixed an issue with usage of RollupFlowBulkProcessor invocable where an inner exception could get inadvertently eaten, reporting success when the actual staged rollup had an error. The isSuccess flag and message fields on the flow output(s) now properly update accordingly.
  • Standardized how Rollup__mdt records are retrieved, fixing for good the issues present with custom fields/objects being used in Rollup__mdt entity definition and field definition fields

Rollup from parent records & Record Triggered Flow documentation update

03 Mar 00:45
Compare
Choose a tag to compare

Fixes #25 by allowing rollup operations to start from the parent records by:

  • adding Rollup__mdt.IsRollupStartedFromParent__c field to allow CMDT Rollup users to flag rollups started from the parent
  • for RollupFlowBulkProcessor invocable, also added Calc Item Type When Rollup Started From Parent because we need to know the child SObject name when Is Rollup Started From Parent is checked off on the Rollup__mdt record
  • for Rollup invocable, in addition to the Calc Item Type When Rollup Started From Parent field above, also added Is Rollup Started From Parent to mirror the approach taken from CMDT

Breaking change for Record Triggered Flows (also added to Readme):

A patch to the Spring 21 release at the end of February introduced a breaking change in the way that the Flow engine hands off Invocable variables to Apex. Currently, if you are using a record triggered flow, you have to use Get Records using the current record's Id in order to populate the Records To Rollup argument properly for both invocables. I will remove this notice when the functionality has been fixed, but there is a bug with simply adding the current record to a collection variable and passing that to the invocable action accordingly. Thank you for your attention to this notice!

Deferred Flow Rollups & CMDT driven flow rollups

24 Feb 17:22
Compare
Choose a tag to compare
  • Fixes #26 by adding CMDT-driven flow rollup support
  • Fixes #38 by adding support for deferring rollups entered in Flow with both Perform Rollup__mdt-based rollup and Perform rollup on records actions when the Defer Processing property is set to {!$GlobalConstant.True}. Rollups deferred in this way must call the Process Deferred Rollups invocable action

Update

  • Removed required attribute from Records to rollup on base invocable to fix issue in Flow engine where if filter criteria are used in a Get Records action and there are no matching results, the Apex action throws an error for the input being null (when it really should be empty). The null check is handled in Apex instead, removing the need for the Flow builder to explicitly check for null on the returned collection.