Skip to content

Commit

Permalink
v1.6.18 - More accurate REFRESH calculations (#571)
Browse files Browse the repository at this point in the history
* Beginning work on new version

* Fixes an issue with NOT(...) clauses in RollupCalcItemReplacer

* Customizing Inner rollups property for full recalc processors

* More accurate counts when adding up relevant children/parents prior to going async. More accurate REFRESH calculations for rollups to multiple parents
  • Loading branch information
jamessimone authored Mar 7, 2024
1 parent c367983 commit 01f5654
Show file tree
Hide file tree
Showing 16 changed files with 226 additions and 36 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ As well, don't miss [the Wiki](../../wiki), which includes even more info for co

## Deployment & Setup

<a href="https://login.salesforce.com/packaging/installPackage.apexp?p0=04t6g000008OafFAAS">
<a href="https://login.salesforce.com/packaging/installPackage.apexp?p0=04t6g000008Oak1AAC">
<img alt="Deploy to Salesforce"
src="./media/deploy-package-to-prod.png">
</a>

<a href="https://test.salesforce.com/packaging/installPackage.apexp?p0=04t6g000008OafFAAS">
<a href="https://test.salesforce.com/packaging/installPackage.apexp?p0=04t6g000008Oak1AAC">
<img alt="Deploy to Salesforce Sandbox"
src="./media/deploy-package-to-sandbox.png">
</a>
Expand Down
15 changes: 15 additions & 0 deletions extra-tests/classes/RollupCalcItemReplacerTests.cls
Original file line number Diff line number Diff line change
Expand Up @@ -162,4 +162,19 @@ private class RollupCalcItemReplacerTests {

System.assertNotEquals(null, updatedContact);
}

@IsTest
static void worksWithParantheticalNotClauses() {
Account acc = [SELECT Id FROM Account];

RollupCalcItemReplacer replacer = new RollupCalcItemReplacer(
new RollupControl__mdt(IsRollupLoggingEnabled__c = true, ReplaceCalcItemsAsyncWhenOverCount__c = 2)
);
acc = (Account) replacer.replace(
new List<Account>{ acc, acc },
new List<Rollup__mdt>{ new Rollup__mdt(CalcItemWhereClause__c = 'NOT(AnnualRevenue != 0 AND Name != null)', CalcItem__c = 'Account') }
)[0];

System.assertEquals(ACC_ANNUAL_REVENUE, acc.AnnualRevenue);
}
}
34 changes: 26 additions & 8 deletions extra-tests/classes/RollupFlowBulkProcessorTests.cls
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,34 @@ private class RollupFlowBulkProcessorTests {
System.assertEquals('No records', outputs[0].message);
}

private class CachedRollup extends Rollup {
public List<Rollup> getCurrentlyCachedRollups() {
return this.getCachedRollups();
}
@IsTest
static void skipsAddingRollupForNoOps() {
RollupFlowBulkProcessor.FlowInput input = new RollupFlowBulkProcessor.FlowInput();
// this contact should be filtered out due to not having an AccountId filled out
input.recordsToRollup = new List<SObject>{ new Contact() };
input.rollupContext = 'INSERT';

Rollup.rollupMetadata = new List<Rollup__mdt>{
new Rollup__mdt(
RollupOperation__c = 'CONCAT',
CalcItem__c = 'Contact',
LookupObject__c = 'Account',
RollupFieldOnCalcItem__c = 'FirstName',
LookupFieldOnCalcItem__c = 'AccountId',
LookupFieldOnLookupObject__c = 'Id',
RollupFieldOnLookupObject__c = 'Name'
)
};

RollupFlowBulkProcessor.addRollup(new List<RollupFlowBulkProcessor.FlowInput>{ input });

System.assertEquals(true, Rollup.CACHED_ROLLUPS.isEmpty());
}

@IsTest
static void shouldAddToRollupsIfCMDTPresent() {
RollupFlowBulkProcessor.FlowInput input = new RollupFlowBulkProcessor.FlowInput();
input.recordsToRollup = new List<SObject>{ new Contact() };
input.recordsToRollup = new List<SObject>{ new Contact(AccountId = RollupTestUtils.createId(Account.SObjectType)) };
input.rollupContext = 'INSERT';

Rollup.rollupMetadata = new List<Rollup__mdt>{
Expand All @@ -44,7 +62,7 @@ private class RollupFlowBulkProcessorTests {
for (Rollup.FlowOutput output : outputs) {
System.assertEquals(true, outputs[0].isSuccess, 'Should not error when adding deferred flow rollup');
}
System.assertNotEquals(true, new CachedRollup().getCurrentlyCachedRollups().isEmpty(), 'Deferred rollup should be kept in buffer');
System.assertNotEquals(true, Rollup.CACHED_ROLLUPS.isEmpty(), 'Deferred rollup should be kept in buffer');
}

@IsTest
Expand Down Expand Up @@ -82,7 +100,7 @@ private class RollupFlowBulkProcessorTests {
RollupFlowBulkProcessor.addRollup(new List<RollupFlowBulkProcessor.FlowInput>{ input });
Test.stopTest();

System.assertEquals(1, new CachedRollup().getCurrentlyCachedRollups().size());
System.assertEquals(1, Rollup.CACHED_ROLLUPS.size());
}

@IsTest
Expand Down Expand Up @@ -196,7 +214,7 @@ private class RollupFlowBulkProcessorTests {

acc = [SELECT AnnualRevenue FROM Account WHERE Id = :acc.Id];
System.assertEquals(5, acc.AnnualRevenue);
System.assertEquals(0, new CachedRollup().getCurrentlyCachedRollups().size(), 'Flow rollup buffer should have been flushed!');
System.assertEquals(0, Rollup.CACHED_ROLLUPS.size(), 'Flow rollup buffer should have been flushed!');
}

@IsTest
Expand Down
61 changes: 60 additions & 1 deletion extra-tests/classes/RollupFlowFullRecalcTests.cls
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ private class RollupFlowFullRecalcTests {

@IsTest
static void shouldRefreshMultipleBatchFullRecalcs() {
Rollup.defaultControl = new RollupControl__mdt(MaxLookupRowsBeforeBatching__c = 1, IsRollupLoggingEnabled__c = true, MaxRollupRetries__c = 3);
Rollup.defaultControl = new RollupControl__mdt(MaxLookupRowsBeforeBatching__c = 0, IsRollupLoggingEnabled__c = true, MaxRollupRetries__c = 3);
Account acc = [SELECT Id FROM Account];
Individual secondParent = new Individual(LastName = 'Second');
insert secondParent;
Expand Down Expand Up @@ -525,4 +525,63 @@ private class RollupFlowFullRecalcTests {
System.assertEquals(1500, updatedAcc.AnnualRevenue, 'SUM REFRESH hierarchy from flow should fully recalc');
System.assertEquals('One, Two', updatedAcc.Name, 'CONCAT_DISTINCT REFRESH hierarchy from flow should full recalc');
}

@IsTest
static void shouldCorrectlyFindAdjacentChildrenForRollupsToMultipleParents() {
List<Account> accounts = new List<Account>{
new Account(Name = 'Parent 1'),
new Account(Name = 'Parent 2'),
new Account(Name = 'Parent 3'),
new Account(Name = 'Parent 4')
};
insert accounts;
Individual bParentOne = new Individual(LastName = 'B1', ConsumerCreditScore = 3, ConvictionsCount = 2);
Individual bParentTwo = new Individual(LastName = 'B2', ConsumerCreditScore = 7, ConvictionsCount = 2);
insert new List<Individual>{ bParentOne, bParentTwo };
List<ContactPointAddress> childrenToInsert = new List<ContactPointAddress>{
new ContactPointAddress(PreferenceRank = 1, ParentId = accounts[0].Id, Name = bParentOne.Id),
new ContactPointAddress(PreferenceRank = 2, ParentId = accounts[1].Id, Name = bParentOne.Id),
new ContactPointAddress(PreferenceRank = 3, ParentId = accounts[2].Id, Name = bParentTwo.Id),
new ContactPointAddress(PreferenceRank = 4, ParentId = accounts[3].Id, Name = bParentTwo.Id)
};
insert childrenToInsert;

List<ContactPointAddress> cpas = new List<ContactPointAddress>{ childrenToInsert[0], childrenToInsert[2] };

Rollup.FlowInput firstInput = RollupTestUtils.prepareFlowTest(cpas, 'REFRESH', 'SUM')[0];
firstInput.deferProcessing = true;
Rollup.FlowInput secondInput = firstInput.clone();
secondInput.lookupFieldOnCalcItem = 'Name';
secondInput.rollupSObjectName = 'Individual';
secondInput.rollupFieldOnOpObject = 'ConsumerCreditScore';
Rollup.FlowInput thirdInput = secondInput.clone();
thirdInput.calcItemWhereClause = 'PreferenceRank > 0';
thirdInput.rollupFieldOnOpObject = 'ConvictionsCount';
thirdInput.rollupOperation = 'COUNT';
Rollup.FlowInput fourthInput = secondInput.clone();
fourthInput.rollupSObjectName = 'Task';
fourthInput.rollupFieldOnOpObject = 'CallDurationInSeconds';
fourthInput.calcItemWhereClause = '(NOT Name LIKE \'' + bParentOne.Id.toString().substring(0, 3) + '%\')';

Test.startTest();
Rollup.performRollup(new List<Rollup.FlowInput>{ firstInput, secondInput, thirdInput, fourthInput });
Rollup.processStoredFlowRollups();
Test.stopTest();

Map<Id, Decimal> accountToExpectedAmount = new Map<Id, Decimal>{
accounts[0].Id => childrenToInsert[0].PreferenceRank,
accounts[1].Id => childrenToInsert[1].PreferenceRank,
accounts[2].Id => childrenToInsert[2].PreferenceRank,
accounts[3].Id => childrenToInsert[3].PreferenceRank
};
for (Account updatedAcc : [SELECT Id, Name, AnnualRevenue FROM Account WHERE Id = :accounts]) {
System.assertEquals(accountToExpectedAmount.get(updatedAcc.Id), updatedAcc.AnnualRevenue, updatedAcc);
}
bParentOne = [SELECT Id, ConsumerCreditScore, ConvictionsCount FROM Individual WHERE Id = :bParentOne.Id];
System.assertEquals(3, bParentOne.ConsumerCreditScore);
System.assertEquals(2, bParentOne.ConvictionsCount);
bParentTwo = [SELECT Id, ConsumerCreditScore, ConvictionsCount FROM Individual WHERE Id = :bParentTwo.Id];
System.assertEquals(7, bParentTwo.ConsumerCreditScore);
System.assertEquals(2, bParentTwo.ConvictionsCount);
}
}
60 changes: 60 additions & 0 deletions extra-tests/classes/RollupFlowTests.cls
Original file line number Diff line number Diff line change
Expand Up @@ -1064,4 +1064,64 @@ private class RollupFlowTests {
Account updatedAcc = [SELECT Id, AnnualRevenue FROM Account WHERE Id = :acc.Id];
System.assertEquals(null, updatedAcc.AnnualRevenue);
}

@IsTest
static void shouldCorrectlyDecrementOnRollupsToMultipleParentsDelete() {
List<Account> accounts = new List<Account>{
new Account(Name = 'Parent 1', AnnualRevenue = 1),
new Account(Name = 'Parent 2', AnnualRevenue = 2),
new Account(Name = 'Parent 3', AnnualRevenue = 3),
new Account(Name = 'Parent 4', AnnualRevenue = 4)
};
insert accounts;
Individual bParentOne = new Individual(LastName = 'B1', ConsumerCreditScore = 3, ConvictionsCount = 2);
Individual bParentTwo = new Individual(LastName = 'B2', ConsumerCreditScore = 7, ConvictionsCount = 2);
insert new List<Individual>{ bParentOne, bParentTwo };
List<ContactPointAddress> childrenToInsert = new List<ContactPointAddress>{
new ContactPointAddress(PreferenceRank = accounts[0].AnnualRevenue.intValue(), ParentId = accounts[0].Id, Name = bParentOne.Id),
new ContactPointAddress(PreferenceRank = accounts[1].AnnualRevenue.intValue(), ParentId = accounts[1].Id, Name = bParentOne.Id),
new ContactPointAddress(PreferenceRank = accounts[2].AnnualRevenue.intValue(), ParentId = accounts[2].Id, Name = bParentTwo.Id),
new ContactPointAddress(PreferenceRank = accounts[3].AnnualRevenue.intValue(), ParentId = accounts[3].Id, Name = bParentTwo.Id)
};
insert childrenToInsert;

List<ContactPointAddress> cpas = new List<ContactPointAddress>{ childrenToInsert[0], childrenToInsert[2] };

Rollup.FlowInput firstInput = RollupTestUtils.prepareFlowTest(cpas, 'DELETE', 'SUM')[0];
firstInput.deferProcessing = true;
Rollup.FlowInput secondInput = firstInput.clone();
secondInput.lookupFieldOnCalcItem = 'Name';
secondInput.rollupSObjectName = 'Individual';
secondInput.rollupFieldOnOpObject = 'ConsumerCreditScore';
Rollup.FlowInput thirdInput = secondInput.clone();
thirdInput.calcItemWhereClause = 'PreferenceRank > 0';
thirdInput.rollupFieldOnOpObject = 'ConvictionsCount';
thirdInput.rollupOperation = 'COUNT';
Rollup.FlowInput fourthInput = secondInput.clone();
fourthInput.rollupSObjectName = 'Task';
fourthInput.rollupFieldOnOpObject = 'CallDurationInSeconds';
fourthInput.calcItemWhereClause = '(NOT Name LIKE \'' + bParentOne.Id.toString().substring(0, 3) + '%\')';

Test.startTest();
Rollup.performRollup(new List<Rollup.FlowInput>{ firstInput, secondInput, thirdInput, fourthInput });
System.assertEquals(3, Rollup.CACHED_ROLLUPS.size());
Rollup.processStoredFlowRollups();
Test.stopTest();

Map<Id, Decimal> accountToExpectedAmount = new Map<Id, Decimal>{
accounts[0].Id => null,
accounts[1].Id => accounts[1].AnnualRevenue,
accounts[2].Id => null,
accounts[3].Id => accounts[3].AnnualRevenue
};
for (Account updatedAcc : [SELECT Id, Name, AnnualRevenue FROM Account WHERE Id = :accounts]) {
System.assertEquals(accountToExpectedAmount.get(updatedAcc.Id), updatedAcc.AnnualRevenue, updatedAcc);
}
bParentOne = [SELECT Id, ConsumerCreditScore, ConvictionsCount FROM Individual WHERE Id = :bParentOne.Id];
System.assertEquals(2, bParentOne.ConsumerCreditScore);
System.assertEquals(1, bParentOne.ConvictionsCount);
bParentTwo = [SELECT Id, ConsumerCreditScore, ConvictionsCount FROM Individual WHERE Id = :bParentTwo.Id];
System.assertEquals(4, bParentTwo.ConsumerCreditScore);
System.assertEquals(1, bParentTwo.ConvictionsCount);
}
}
4 changes: 2 additions & 2 deletions extra-tests/classes/RollupFullRecalcTests.cls
Original file line number Diff line number Diff line change
Expand Up @@ -1624,7 +1624,7 @@ private class RollupFullRecalcTests {

RollupFullBatchRecalculator fullRecalc = new RollupFullBatchRecalculator(
'SELECT Id, PreferenceRank, ParentId FROM ContactPointAddress',
Rollup.InvocationPoint.FROM_APEX,
Rollup.InvocationPoint.FROM_FULL_RECALC_LWC,
new List<Rollup__mdt>{
new Rollup__mdt(
CalcItem__c = 'ContactPointAddress',
Expand Down Expand Up @@ -1664,7 +1664,7 @@ private class RollupFullRecalcTests {

RollupFullBatchRecalculator fullRecalc = new RollupFullBatchRecalculator(
'SELECT Id, PreferenceRank, ParentId FROM ContactPointAddress',
Rollup.InvocationPoint.FROM_APEX,
Rollup.InvocationPoint.FROM_FULL_RECALC_LWC,
new List<Rollup__mdt>{
new Rollup__mdt(
CalcItem__c = 'ContactPointAddress',
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "apex-rollup",
"version": "1.6.17",
"version": "1.6.18",
"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",
Expand Down
4 changes: 2 additions & 2 deletions rollup-namespaced/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ For more info, see the base `README`.

## Deployment & Setup

<a href="https://login.salesforce.com/packaging/installPackage.apexp?p0=04t6g000008OafKAAS">
<a href="https://login.salesforce.com/packaging/installPackage.apexp?p0=04t6g000008Oak6AAC">
<img alt="Deploy to Salesforce"
src="./media/deploy-package-to-prod.png">
</a>

<a href="https://test.salesforce.com/packaging/installPackage.apexp?p0=04t6g000008OafKAAS">
<a href="https://test.salesforce.com/packaging/installPackage.apexp?p0=04t6g000008Oak6AAC">
<img alt="Deploy to Salesforce Sandbox"
src="./media/deploy-package-to-sandbox.png">
</a>
2 changes: 1 addition & 1 deletion rollup-namespaced/sfdx-project.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": "04t6g000008OafKAAS"
"apex-rollup-namespaced@1.1.17": "04t6g000008Oak6AAC"
}
}
Loading

0 comments on commit 01f5654

Please sign in to comment.