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 - + Deploy to Salesforce - + Deploy to Salesforce Sandbox 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 - + Deploy to Salesforce - + Deploy to Salesforce Sandbox 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