From b7cafd8f459a5666142d8655e9099684c2762cd1 Mon Sep 17 00:00:00 2001
From: James Simone <16430727+jamessimone@users.noreply.github.com>
Date: Tue, 16 Apr 2024 08:59:15 -0600
Subject: [PATCH] v1.6.22 - Grandparent COUNT_DISTINCT deletion bugfix (#582)
* Fixes #581 by properly handling COUNT_DISTINCT for grandparent rollup deletions
---
README.md | 4 +-
.../classes/RollupIntegrationTests.cls | 47 +++++++++++++++++++
package.json | 2 +-
rollup-namespaced/README.md | 4 +-
rollup-namespaced/sfdx-project.json | 2 +-
rollup/core/classes/RollupAsyncProcessor.cls | 4 +-
rollup/core/classes/RollupLogger.cls | 2 +-
.../classes/RollupRelationshipFieldFinder.cls | 3 ++
sfdx-project.json | 7 +--
9 files changed, 64 insertions(+), 11 deletions(-)
diff --git a/README.md b/README.md
index 048d7697..2be74672 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
-
+
-
+
diff --git a/extra-tests/classes/RollupIntegrationTests.cls b/extra-tests/classes/RollupIntegrationTests.cls
index 36061b89..825d475a 100644
--- a/extra-tests/classes/RollupIntegrationTests.cls
+++ b/extra-tests/classes/RollupIntegrationTests.cls
@@ -673,6 +673,53 @@ private class RollupIntegrationTests {
System.assertEquals(greatGrandparent.Name, updatedGreatGrandparent.Name, 'Great-grandparent name should not have been appended based on exclusions');
}
+ @IsTest
+ static void shouldCountDistinctForGrandparentDeletes() {
+ if (RollupTestUtils.IS_NAMESPACED_PACKAGE_ORG) {
+ return;
+ }
+
+ Rollup.onlyUseMockMetadata = true;
+ Rollup.shouldFlattenAsyncProcesses = true;
+ Rollup.rollupMetadata = new List{
+ new Rollup__mdt(
+ CalcItem__c = ApplicationLog__c.SObjectType.getDescribe(SObjectDescribeOptions.DEFERRED).getName(),
+ RollupFieldOnCalcItem__c = 'Name',
+ LookupFieldOnCalcItem__c = ApplicationLog__c.Application__c.getDescribe().getName(),
+ LookupObject__c = 'Account',
+ LookupFieldOnLookupObject__c = 'Id',
+ RollupFieldOnLookupObject__c = 'AnnualRevenue',
+ RollupOperation__c = 'COUNT_DISTINCT',
+ GrandparentRelationshipFieldPath__c = RollupTestUtils.getRelationshipPath(
+ new List{ ApplicationLog__c.Application__c, Application__c.ParentApplication__c, ParentApplication__c.Account__c, Account.Name }
+ )
+ )
+ };
+
+ Account greatGrandparent = new Account(Name = 'Great-grandparent 1');
+ insert greatGrandparent;
+
+ ParentApplication__c grandParent = new ParentApplication__c(Name = 'Grandparent 1', Account__c = greatGrandparent.Id);
+ ParentApplication__c secondGrandparent = new ParentApplication__c(Name = 'Grandparent 2', Account__c = greatGrandparent.Id);
+ List parentApps = new List{ grandParent, secondGrandparent };
+ insert parentApps;
+
+ Application__c parent = new Application__c(Name = 'Parent 1', ParentApplication__c = grandParent.Id);
+ Application__c secondParent = new Application__c(Name = 'Parent 2', ParentApplication__c = secondGrandparent.Id);
+ insert new List{ parent, secondParent };
+
+ ApplicationLog__c child = new ApplicationLog__c(Application__c = secondParent.Id, Name = 'Will Still Exist');
+ ApplicationLog__c secondChild = new ApplicationLog__c(Name = 'To be deleted', Application__c = parent.Id);
+ insert new List{ child, secondChild };
+
+ Test.startTest();
+ delete secondChild;
+ Test.stopTest();
+
+ greatGrandparent = [SELECT AnnualRevenue FROM Account WHERE Id = :greatGrandparent.Id];
+ Assert.areEqual(1, greatGrandparent.AnnualRevenue, 'Should still count non-deleted great-grandchild');
+ }
+
@IsTest
static void shouldProperlyFilterPolymorphicWhatFields() {
Account acc = new Account(Name = 'Matching type');
diff --git a/package.json b/package.json
index a9b74fe9..5f4df135 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "apex-rollup",
- "version": "1.6.21",
+ "version": "1.6.22",
"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 30fca670..3db50e81 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 397a41c0..cc4af81a 100644
--- a/rollup-namespaced/sfdx-project.json
+++ b/rollup-namespaced/sfdx-project.json
@@ -25,6 +25,6 @@
"apex-rollup-namespaced@1.1.13": "04t6g000008OaYwAAK",
"apex-rollup-namespaced@1.1.14": "04t6g000008OaZBAA0",
"apex-rollup-namespaced@1.1.16": "04t6g000008OaZaAAK",
- "apex-rollup-namespaced@1.1.17": "04t6g000008OatxAAC"
+ "apex-rollup-namespaced@1.1.17": "04t6g000008OavFAAS"
}
}
\ No newline at end of file
diff --git a/rollup/core/classes/RollupAsyncProcessor.cls b/rollup/core/classes/RollupAsyncProcessor.cls
index d9b0b9e6..d6c79760 100644
--- a/rollup/core/classes/RollupAsyncProcessor.cls
+++ b/rollup/core/classes/RollupAsyncProcessor.cls
@@ -586,7 +586,9 @@ global virtual without sharing class RollupAsyncProcessor extends Rollup impleme
// calling clear in a loop here might look interesting - and it would be a massive problem if not for the
// bag only responding to the very first clear() invocation. everything after that is a no-op (so, any rollup with more
// than one rollup operation going at a time)
- if (rollup.triggerContext == System.TriggerOperation.BEFORE_DELETE || rollup.op.name().contains('DELETE')) {
+ if (
+ (rollup.triggerContext == System.TriggerOperation.BEFORE_DELETE || rollup.op.name().contains('DELETE')) && rollup.traversal?.getIsFinished() != true
+ ) {
bag.clear();
}
}
diff --git a/rollup/core/classes/RollupLogger.cls b/rollup/core/classes/RollupLogger.cls
index 9febc451..24b5afa8 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.21';
+ private static final String CURRENT_VERSION_NUMBER = 'v1.6.22';
private static final System.LoggingLevel FALLBACK_LOGGING_LEVEL = System.LoggingLevel.DEBUG;
private static final RollupPlugin PLUGIN = new RollupPlugin();
diff --git a/rollup/core/classes/RollupRelationshipFieldFinder.cls b/rollup/core/classes/RollupRelationshipFieldFinder.cls
index a05ea6eb..73c24afe 100644
--- a/rollup/core/classes/RollupRelationshipFieldFinder.cls
+++ b/rollup/core/classes/RollupRelationshipFieldFinder.cls
@@ -654,6 +654,9 @@ public without sharing class RollupRelationshipFieldFinder {
.setArg(inclusiveIds)
.setArg(bindVar, this.records)
.get();
+ if (this.metadata.RollupOperation__c.contains('DELETE')) {
+ this.records.clear();
+ }
this.records.addAll(additionalCalcItems);
return additionalCalcItems;
} catch (Exception ex) {
diff --git a/sfdx-project.json b/sfdx-project.json
index e4ce641d..8cb09e36 100644
--- a/sfdx-project.json
+++ b/sfdx-project.json
@@ -5,8 +5,8 @@
"package": "apex-rollup",
"path": "rollup",
"scopeProfiles": true,
- "versionName": "Updating to null coalesce operator when applicable",
- "versionNumber": "1.6.21.0",
+ "versionName": "Fixes grandparent rollup logic for deletes with COUNT_DISTINCT",
+ "versionNumber": "1.6.22.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": {
@@ -104,6 +104,7 @@
"apex-rollup@1.6.18": "04t6g000008Oak1AAC",
"apex-rollup@1.6.19": "04t6g000008Oal4AAC",
"apex-rollup@1.6.20": "04t6g000008OanPAAS",
- "apex-rollup@1.6.21": "04t6g000008OatsAAC"
+ "apex-rollup@1.6.21": "04t6g000008OatsAAC",
+ "apex-rollup@1.6.22": "04t6g000008OavAAAS"
}
}
\ No newline at end of file