diff --git a/README.md b/README.md
index 42104e1a..4a3a48cf 100644
--- a/README.md
+++ b/README.md
@@ -24,12 +24,12 @@ As well, don't miss [the Wiki](../../wiki), which includes even more info for co
## Deployment & Setup
-
+
-
+
@@ -453,12 +453,15 @@ global static void runFromCDCTrigger()
// imperatively from Apex, relying on CMDT for additional rollup info
// if you are actually using this from WITHIN a trigger, the second argument should
-// ALWAYS be the "Trigger.operationType" static variable
-global static void runFromApex(List calcItems, TriggerOperation rollupContext)
+// ALWAYS be the "Trigger.operationType" static variable (unless you're unit testing)
+global static void runFromApex(List children, TriggerOperation rollupContext)
+
+// overload of the above, with support for the Trigger.oldMap variable (or your unit-tested approximation thereof)
+global static void runFromApex(List children, Map oldChildrenMap, TriggerOperation rollupContext)
// for more info on how this method differs from the one above it, check out the "Parent Level Merges" section!
// for anything OTHER than merge situations use of this method is an anti-pattern
-global static Rollup runFromApex(List rollupMetadata, Evaluator eval, List calcItems, Map oldCalcItems)
+global static Rollup runFromApex(List rollupMetadata, Evaluator eval, List children, Map oldChildrenMap)
// imperatively from Apex with arguments taking the place of values previously supplied by CMDT
// can be used in conjunction with "batch" to group rollup operations (as seen in the example preceding this section)
diff --git a/extra-tests/classes/RollupIntegrationTests.cls b/extra-tests/classes/RollupIntegrationTests.cls
index eabee044..5ec7919d 100644
--- a/extra-tests/classes/RollupIntegrationTests.cls
+++ b/extra-tests/classes/RollupIntegrationTests.cls
@@ -1625,7 +1625,6 @@ private class RollupIntegrationTests {
new ContactPointAddress(Id = RollupTestUtils.createId(ContactPointAddress.SObjectType), ParentId = acc.Id, PreferenceRank = 10)
};
- Rollup.records = cpas;
Rollup.rollupMetadata = new List{
new Rollup__mdt(
RollupFieldOnCalcItem__c = 'PreferenceRank',
@@ -1646,6 +1645,42 @@ private class RollupIntegrationTests {
System.assertEquals(15, acc.AnnualRevenue);
}
+ @IsTest
+ static void shouldRunWithOldRecordsDirectlyFromApex() {
+ Account acc = [SELECT Id FROM Account];
+
+ List cpas = new List{
+ new ContactPointAddress(Id = RollupTestUtils.createId(ContactPointAddress.SObjectType), ParentId = acc.Id, PreferenceRank = 5),
+ new ContactPointAddress(Id = RollupTestUtils.createId(ContactPointAddress.SObjectType), ParentId = acc.Id, PreferenceRank = 10)
+ };
+
+ Rollup.rollupMetadata = new List{
+ new Rollup__mdt(
+ RollupFieldOnCalcItem__c = 'PreferenceRank',
+ LookupObject__c = 'Account',
+ LookupFieldOnCalcItem__c = 'ParentId',
+ LookupFieldOnLookupObject__c = 'Id',
+ RollupFieldOnLookupObject__c = 'AnnualRevenue',
+ RollupOperation__c = 'SUM',
+ CalcItem__c = 'ContactPointAddress'
+ )
+ };
+
+ Test.startTest();
+ Rollup.runFromApex(
+ cpas,
+ new Map{
+ cpas[0].Id => new ContactPointAddress(Id = cpas[0].Id, ParentId = acc.Id, PreferenceRank = 0),
+ cpas[1].Id => new ContactPointAddress(Id = cpas[1].Id, ParentId = acc.Id, PreferenceRank = 0)
+ },
+ TriggerOperation.AFTER_UPDATE
+ );
+ Test.stopTest();
+
+ acc = [SELECT AnnualRevenue FROM Account];
+ System.assertEquals(15, acc.AnnualRevenue);
+ }
+
@IsTest
static void shouldDeferUpdateWhenMaxParentRowsLessThanCurrentUpdateRows() {
Account acc = [SELECT Id FROM Account];
diff --git a/package.json b/package.json
index 534ad408..b4684684 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "apex-rollup",
- "version": "1.6.31",
+ "version": "1.6.32",
"description": "Fast, configurable, elastically scaling custom rollup solution. Apex Invocable action, one-liner Apex trigger/CMDT-driven logic, and scheduled Apex-ready.",
"repository": {
"type": "git",
diff --git a/rollup-namespaced/README.md b/rollup-namespaced/README.md
index 8d3f723d..d8d8992b 100644
--- a/rollup-namespaced/README.md
+++ b/rollup-namespaced/README.md
@@ -18,12 +18,12 @@ For more info, see the base `README`.
## Deployment & Setup
-
+
-
+
diff --git a/rollup-namespaced/sfdx-project.json b/rollup-namespaced/sfdx-project.json
index 221cb804..b351d95a 100644
--- a/rollup-namespaced/sfdx-project.json
+++ b/rollup-namespaced/sfdx-project.json
@@ -4,8 +4,8 @@
"default": true,
"package": "apex-rollup-namespaced",
"path": "rollup-namespaced/source/rollup",
- "versionName": "Fixes issue where sync rollups with lowercase field names in where clauses would not start up properly",
- "versionNumber": "1.1.24.0",
+ "versionName": "Adds imperative Apex method Rollup.runFromApex for new and old record code paths",
+ "versionNumber": "1.1.25.0",
"versionDescription": "Fast, configurable, elastically scaling custom rollup solution. Apex Invocable action, one-liner Apex trigger/CMDT-driven logic, and scheduled Apex-ready.",
"releaseNotesUrl": "https://github.com/jamessimone/apex-rollup/releases/latest",
"unpackagedMetadata": {
@@ -27,6 +27,7 @@
"apex-rollup-namespaced@1.1.21": "04t6g000008ObLCAA0",
"apex-rollup-namespaced@1.1.22": "04t6g000008ObNDAA0",
"apex-rollup-namespaced@1.1.23": "04t6g000008ObNSAA0",
- "apex-rollup-namespaced@1.1.24": "04t6g000008ObbqAAC"
+ "apex-rollup-namespaced@1.1.24": "04t6g000008ObbqAAC",
+ "apex-rollup-namespaced@1.1.25": "04t6g000008Obc0AAC"
}
-}
\ No newline at end of file
+}
diff --git a/rollup/core/classes/Rollup.cls b/rollup/core/classes/Rollup.cls
index 397f09d2..4cbfd779 100644
--- a/rollup/core/classes/Rollup.cls
+++ b/rollup/core/classes/Rollup.cls
@@ -5,7 +5,7 @@ global without sharing virtual class Rollup implements RollupLogger.ToStringObje
* but this keeps things much simpler
*/
@TestVisible
- private static Boolean shouldRun = false;
+ private static Boolean shouldRun;
@TestVisible
private static TriggerOperation apexContext;
@TestVisible
@@ -1699,12 +1699,9 @@ global without sharing virtual class Rollup implements RollupLogger.ToStringObje
* - TriggerOperation.BEFORE_DELETE
* - TriggerOperation.AFTER_UNDELETE
*
- * Note that while it's an anti-pattern to call this from directly within a Trigger,
- * because `runFromTrigger()` coupled with CMDT is the better option,
- * you should pass: `Trigger.operationType` for the second argument if you do.
*/
- global static void runFromApex(List calcItems, TriggerOperation rollupContext) {
- shouldRun = true;
+ global static void runFromApex(List calcItems, System.TriggerOperation rollupContext) {
+ shouldRun = shouldRun ?? true;
records = calcItems;
apexContext = rollupContext;
@@ -1715,6 +1712,12 @@ global without sharing virtual class Rollup implements RollupLogger.ToStringObje
apexContext = null;
}
+ global static void runFromApex(List children, Map oldChildrenMap, System.TriggerOperation rollupContext) {
+ oldChildrenMap = oldChildrenMap;
+ runFromApex(children, rollupContext);
+ oldChildrenMap = null;
+ }
+
global static Rollup runFromApex(List localMetas, Evaluator eval, List calcItems, Map oldCalcItems) {
Rollup rollupConductor = RollupAsyncProcessor.getConductor(InvocationPoint.FROM_APEX, calcItems, oldCalcItems);
if (shouldRunFromTrigger() == false || localMetas.isEmpty()) {
@@ -2828,7 +2831,7 @@ global without sharing virtual class Rollup implements RollupLogger.ToStringObje
* because the underlying SObject can't be modified till afterwards
*/
private static Boolean shouldRunFromTrigger() {
- shouldRun = shouldRun || Trigger.isExecuting;
+ shouldRun = Trigger.isExecuting || (shouldRun ?? false);
if (Trigger.operationType != null && isCDC == false) {
apexContext = Trigger.operationType;
}
diff --git a/rollup/core/classes/RollupLogger.cls b/rollup/core/classes/RollupLogger.cls
index 41701573..b623150f 100644
--- a/rollup/core/classes/RollupLogger.cls
+++ b/rollup/core/classes/RollupLogger.cls
@@ -1,7 +1,7 @@
global without sharing virtual class RollupLogger implements ILogger {
@TestVisible
// this gets updated via the pipeline as the version number gets incremented
- private static final String CURRENT_VERSION_NUMBER = 'v1.6.31';
+ private static final String CURRENT_VERSION_NUMBER = 'v1.6.32';
private static final System.LoggingLevel FALLBACK_LOGGING_LEVEL = System.LoggingLevel.DEBUG;
private static final RollupPlugin PLUGIN = new RollupPlugin();
diff --git a/sfdx-project.json b/sfdx-project.json
index 8114c81e..9703a20d 100644
--- a/sfdx-project.json
+++ b/sfdx-project.json
@@ -5,8 +5,8 @@
"package": "apex-rollup",
"path": "rollup",
"scopeProfiles": true,
- "versionName": "Fixes issue where sync rollups with lowercase field names in where clauses would not start up properly",
- "versionNumber": "1.6.31.0",
+ "versionName": "Adds imperative Apex method Rollup.runFromApex for new and old record code paths",
+ "versionNumber": "1.6.32.0",
"versionDescription": "Fast, configurable, elastically scaling custom rollup solution. Apex Invocable action, one-liner Apex trigger/CMDT-driven logic, and scheduled Apex-ready.",
"releaseNotesUrl": "https://github.com/jamessimone/apex-rollup/releases/latest",
"unpackagedMetadata": {
@@ -101,10 +101,10 @@
"Apex Rollup - Rollup Callback@0.0.3-0": "04t6g000008Sis0AAC",
"Nebula Logger - Core@4.8.0-NEXT-ignore-origin-method": "04t5Y0000015lslQAA",
"apex-rollup": "0Ho6g000000TNcOCAW",
- "apex-rollup@1.6.27": "04t6g000008ObL7AAK",
"apex-rollup@1.6.28": "04t6g000008ObN8AAK",
"apex-rollup@1.6.29": "04t6g000008ObNNAA0",
"apex-rollup@1.6.30": "04t6g000008ObVhAAK",
- "apex-rollup@1.6.31": "04t6g000008ObblAAC"
+ "apex-rollup@1.6.31": "04t6g000008ObblAAC",
+ "apex-rollup@1.6.32": "04t6g000008ObbvAAC"
}
-}
\ No newline at end of file
+}