Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v1.7.2 - RollupCalcItemReplacer bugfix #642

Merged
merged 2 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ 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=04t6g000008OfWQAA0">
<a href="https://login.salesforce.com/packaging/installPackage.apexp?p0=04t6g000008OfXTAA0">
<img alt="Deploy to Salesforce" src="./media/deploy-package-to-prod.png">
</a>

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

Assert.areEqual(0, records.size());
}

@IsTest
static void doesNotReplaceForCustomTypeFields() {
List<Account> accounts = [SELECT Id FROM Account];
RollupCalcItemReplacer replacer = new RollupCalcItemReplacer(
new RollupControl__mdt(IsRollupLoggingEnabled__c = true, ReplaceCalcItemsAsyncWhenOverCount__c = 3)
);
List<Rollup__mdt> metas = new List<Rollup__mdt>{ new Rollup__mdt(CalcItemWhereClause__c = 'Parent.Type__r = \'hello\'', CalcItem__c = 'Account') };

List<SObject> records = replacer.replace(accounts, metas);

Assert.areEqual(1, records.size());
Assert.isTrue(replacer.hasProcessedMetadata(metas, accounts));
}
}
58 changes: 58 additions & 0 deletions extra-tests/classes/RollupFlowBulkProcessorTests.cls
Original file line number Diff line number Diff line change
Expand Up @@ -639,4 +639,62 @@ private class RollupFlowBulkProcessorTests {
Individual updatedIndy = [SELECT Id, ConsumerCreditScore FROM Individual WHERE Id = :indy.Id];
System.assertEquals(secondChild.AnnualRevenue, updatedIndy.ConsumerCreditScore);
}

@IsTest
static void doesNotNoOpForSomeAllNoneRollups() {
Rollup.rollupMetadata = new List<Rollup__mdt>{
new Rollup__mdt(
RollupFieldOnCalcItem__c = 'Id',
LookupObject__c = 'Account',
LookupFieldOnCalcItem__c = 'AccountId',
LookupFieldOnLookupObject__c = 'Id',
RollupFieldOnLookupObject__c = 'AnnualRevenue',
RollupOperation__c = 'SOME',
CalcItem__c = 'Contact',
CalcItemWhereClause__c = 'FirstName != \'One\''
),
new Rollup__mdt(
RollupFieldOnCalcItem__c = 'Id',
LookupObject__c = 'Account',
LookupFieldOnCalcItem__c = 'AccountId',
LookupFieldOnLookupObject__c = 'Id',
RollupFieldOnLookupObject__c = 'Description',
RollupOperation__c = 'ALL',
CalcItem__c = 'Contact',
CalcItemWhereClause__c = 'FirstName != \'One\''
),
new Rollup__mdt(
RollupFieldOnCalcItem__c = 'Id',
LookupObject__c = 'Account',
LookupFieldOnCalcItem__c = 'AccountId',
LookupFieldOnLookupObject__c = 'Id',
RollupFieldOnLookupObject__c = 'NumberOfEmployees',
RollupOperation__c = 'NONE',
CalcItem__c = 'Contact',
CalcItemWhereClause__c = 'FirstName != \'One\''
)
};
Rollup.onlyUseMockMetadata = true;
Account acc = (Account) RollupTestUtils.queryRecord(Account.SObjectType, new List<Schema.SObjectField>());
acc.Description = 'true';
acc.AnnualRevenue = 1;
acc.NumberOfEmployees = 0;
RollupAsyncProcessor.stubParentRecords = new List<SObject>{ acc };

Rollup.records = new List<Contact>{ new Contact(FirstName = 'One', AccountId = acc.Id) };

RollupFlowBulkProcessor.FlowInput input = new RollupFlowBulkProcessor.FlowInput();
input.recordsToRollup = new List<Contact>{ new Contact(FirstName = 'One', AccountId = acc.Id, Id = RollupTestUtils.createId(Contact.SObjectType)) };
input.oldRecordsToRollup = new List<SObject>{ new Contact(Id = input.recordsToRollup[0].Id, FirstName = 'One', AccountId = acc.Id) };
input.rollupContext = 'UPDATE';
input.deferProcessing = false;

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

Assert.areEqual('false', acc.Description);
Assert.areEqual(0, acc.AnnualRevenue);
Assert.areEqual(1, acc.NumberOfEmployees);
}
}
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.7.1",
"version": "1.7.2",
"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=04t6g000008OfWVAA0">
<a href="https://login.salesforce.com/packaging/installPackage.apexp?p0=04t6g000008OfXYAA0">
<img alt="Deploy to Salesforce"
src="./media/deploy-package-to-prod.png">
</a>

<a href="https://test.salesforce.com/packaging/installPackage.apexp?p0=04t6g000008OfWVAA0">
<a href="https://test.salesforce.com/packaging/installPackage.apexp?p0=04t6g000008OfXYAA0">
<img alt="Deploy to Salesforce Sandbox"
src="./media/deploy-package-to-sandbox.png">
</a>
7 changes: 4 additions & 3 deletions rollup-namespaced/sfdx-project.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
"default": true,
"package": "apex-rollup-namespaced",
"path": "rollup-namespaced/source/rollup",
"versionName": "Scheduled Rollup updates, RollupDateLiteral updates",
"versionNumber": "1.2.1.0",
"versionName": "Fixes issue in RollupCalcItemReplacer where custom Type fields were incorrectly flagged as polymorphic",
"versionNumber": "1.2.2.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": {
Expand All @@ -26,6 +26,7 @@
"apex-rollup-namespaced@1.1.29": "04t6g000008OfMjAAK",
"apex-rollup-namespaced@1.1.30": "04t6g000008OfSJAA0",
"apex-rollup-namespaced@1.2.0": "04t6g000008OfU0AAK",
"apex-rollup-namespaced@1.2.1": "04t6g000008OfWVAA0"
"apex-rollup-namespaced@1.2.1": "04t6g000008OfWVAA0",
"apex-rollup-namespaced@1.2.2": "04t6g000008OfXYAA0"
}
}
2 changes: 1 addition & 1 deletion rollup/core/classes/Rollup.cls
Original file line number Diff line number Diff line change
Expand Up @@ -2850,7 +2850,7 @@ global without sharing virtual class Rollup implements RollupLogger.ToStringObje
/**
* - in order to accomodate CDC, we set the apexContext manually there
* since technically all CDC is done from an AFTER_INSERT context
* - an undelete behaviors _strictly_ the same as an insert
* - an undelete behaves _strictly_ the same as an insert
* because the underlying SObject can't be modified till afterwards
*/
private static Boolean shouldRunFromTrigger() {
Expand Down
12 changes: 6 additions & 6 deletions rollup/core/classes/RollupCalcItemReplacer.cls
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ public without sharing class RollupCalcItemReplacer {

private void processWhereClauseForDownstreamEvals(Schema.SObjectType sObjectType, Rollup__mdt metadata, RollupEvaluator.WhereFieldEvaluator whereEval) {
for (String whereClause : whereEval.getWhereClauses()) {
Boolean hasTypeField = whereClause.contains(TYPE_FIELD);
Boolean hasTypeField = whereClause.split(TYPE_FIELD + '(?!__r)').size() > 1;
Boolean hasOwnerField = whereClause.contains(OWNER);
if (hasTypeField == false && hasOwnerField == false) {
continue;
Expand Down Expand Up @@ -340,8 +340,8 @@ public without sharing class RollupCalcItemReplacer {
Map<String, SObjectField> fieldNameToFieldToken = calcItems[0].getSObjectType().getDescribe().fields.getMap();
for (Integer index = 0; index < calcItems.size(); index++) {
SObject calcItem = calcItems[index];
SObject calcItemWIthUpdatedParentField = idToCalcItemsWithParentFields.get(calcItem.Id);
Map<String, Object> updatedParentFields = calcItemWIthUpdatedParentField?.getPopulatedFieldsAsMap() ?? new Map<String, Object>();
SObject calcItemWithUpdatedParentField = idToCalcItemsWithParentFields.get(calcItem.Id);
Map<String, Object> updatedParentFields = calcItemWithUpdatedParentField?.getPopulatedFieldsAsMap() ?? new Map<String, Object>();
for (String fieldName : updatedParentFields.keySet()) {
Schema.DescribeFieldResult fieldToken = fieldNameToFieldToken.get(fieldName)?.getDescribe();
Boolean isSkippableField = fieldToken?.getReferenceTo().isEmpty() != false || fieldToken?.getName() == 'Id';
Expand All @@ -353,23 +353,23 @@ public without sharing class RollupCalcItemReplacer {
try {
SObject parent = calcItem.getSObject(fieldToken.getRelationshipName());
if (parent == null) {
calcItem.putSObject(fieldToken.getRelationshipName(), calcItemWIthUpdatedParentField.getSObject(fieldToken.getRelationshipName()));
calcItem.putSObject(fieldToken.getRelationshipName(), calcItemWithUpdatedParentField.getSObject(fieldToken.getRelationshipName()));
} else {
parent.put(fieldName, updatedParentFields.get(fieldName));
}
} catch (SObjectException ex) {
// avoids "System.SObjectException: Relationship { relationship name } is not editable"
if (updatedParentFields.containsKey(fieldToken.getRelationshipName())) {
String relationshipName = fieldToken.getRelationshipName();
calcItems.set(index, serializeReplace(calcItem, relationshipName, calcItemWIthUpdatedParentField.getSObject(relationshipName)));
calcItems.set(index, serializeReplace(calcItem, relationshipName, calcItemWithUpdatedParentField.getSObject(relationshipName)));
}
}
} else {
// polymorphic parent fields that are returned from SOQL can get retrieved via .getSObject,
// but can't be appended via .putSObject without reinitializing the parent object to its actual type
// this is because they are returned with type "Name", and avoids the dreaded:
// "System.SObjectException: Illegal assignment from Name to { the calcItem type }"
SObject parentFieldObject = calcItemWIthUpdatedParentField.getSObject(fieldToken.getRelationshipName());
SObject parentFieldObject = calcItemWithUpdatedParentField.getSObject(fieldToken.getRelationshipName());
SObject replacementObject = parentFieldObject.Id.getSObjectType().newSObject();
for (String populatedFieldName : parentFieldObject.getPopulatedFieldsAsMap().keySet()) {
replacementObject.put(populatedFieldName, parentFieldObject.get(populatedFieldName));
Expand Down
2 changes: 1 addition & 1 deletion rollup/core/classes/RollupLogger.cls
Original file line number Diff line number Diff line change
@@ -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.7.1';
private static final String CURRENT_VERSION_NUMBER = 'v1.7.2';
private static final System.LoggingLevel FALLBACK_LOGGING_LEVEL = System.LoggingLevel.DEBUG;
private static final RollupPlugin PLUGIN = new RollupPlugin();

Expand Down
7 changes: 4 additions & 3 deletions sfdx-project.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
"package": "apex-rollup",
"path": "rollup",
"scopeProfiles": true,
"versionName": "Scheduled Rollup updates, RollupDateLiteral updates",
"versionNumber": "1.7.1.0",
"versionName": "Fixes issue in RollupCalcItemReplacer where custom Type fields were incorrectly flagged as polymorphic",
"versionNumber": "1.7.2.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": {
Expand Down Expand Up @@ -107,6 +107,7 @@
"apex-rollup@1.6.36": "04t6g000008OfMeAAK",
"apex-rollup@1.6.37": "04t6g000008OfSEAA0",
"apex-rollup@1.7.0": "04t6g000008OfTvAAK",
"apex-rollup@1.7.1": "04t6g000008OfWQAA0"
"apex-rollup@1.7.1": "04t6g000008OfWQAA0",
"apex-rollup@1.7.2": "04t6g000008OfXTAA0"
}
}