Skip to content

Commit c893d38

Browse files
authored
V1.1.7 - easier imperative Apex, fix truncation on update (#50)
* Fix for #49 by enabling truncation on update * Fix #48 by adding "runFromApex" method for imperative Apex runs using CMDT
1 parent 5700f3e commit c893d38

File tree

4 files changed

+81
-10
lines changed

4 files changed

+81
-10
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,11 @@ public static void runFromTrigger()
234234
// more on that in the CDC section of "Special Considerations", below
235235
public static void runFromCDCTrigger()
236236

237+
// imperatively from Apex, relying on CMDT for additional rollup info
238+
global static void runFromApex(List<SObject> calcItems, TriggerOperation rollupContext)
239+
240+
// imperatively from Apex with arguments taking the place of values previously supplied by CMDT
241+
// can be used in conjunction with "batch" to group rollup operations (as seen in the example preceding this section)
237242
global static Rollup averageFromApex(
238243
SObjectField averageFieldOnCalcItem,
239244
SObjectField lookupFieldOnCalcItem,

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "apex-rollup",
3-
"version": "1.1.6",
3+
"version": "1.1.7",
44
"description": "Fast, configurable, elastically scaling custom rollup solution. Apex Invocable action, one-liner Apex trigger/CMDT-driven logic, and scheduled Apex-ready.",
55
"repository": {
66
"type": "git",

rollup/main/default/classes/Rollup.cls

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1307,9 +1307,29 @@ global without sharing virtual class Rollup implements Database.Batchable<SObjec
13071307
}
13081308

13091309
global static void runFromTrigger() {
1310-
SObjectType sObjectType = getTriggerRecords().getSObjectType();
1311-
List<Rollup__mdt> rollupMetadata = getTriggerRollupMetadata(sObjectType);
1312-
runFromApex(rollupMetadata, null, getTriggerRecords(), getOldTriggerRecordsMap()).runCalc();
1310+
List<SObject> triggerRecords = getTriggerRecords();
1311+
List<Rollup__mdt> rollupMetadata = getTriggerRollupMetadata(triggerRecords.getSObjectType());
1312+
runFromApex(rollupMetadata, null, triggerRecords, getOldTriggerRecordsMap()).runCalc();
1313+
}
1314+
1315+
/**
1316+
* @param `List<SObject>` calcItems - the records whose values you'd like to roll up
1317+
* @param `TriggerOperation` rollupContext - acceptable values are:
1318+
* - TriggerOperation.AFTER_INSERT
1319+
* - TriggerOperation.AFTER_UDATE
1320+
* - TriggerOperation.BEFORE_DELETE
1321+
* - TriggerOperation.AFTER_UNDELETE
1322+
*/
1323+
global static void runFromApex(List<SObject> calcItems, TriggerOperation rollupContext) {
1324+
shouldRun = true;
1325+
records = calcItems;
1326+
apexContext = rollupContext;
1327+
1328+
runFromTrigger();
1329+
1330+
records = null;
1331+
shouldRun = null;
1332+
apexContext = null;
13131333
}
13141334

13151335
private static Rollup runFromApex(List<Rollup__mdt> rollupMetadata, Evaluator eval, List<SObject> calcItems, Map<Id, SObject> oldCalcItems) {
@@ -1437,14 +1457,14 @@ global without sharing virtual class Rollup implements Database.Batchable<SObjec
14371457
SELECT
14381458
// we have to do transforms on these fields because custom objects/custom fields
14391459
// have references that otherwise won't work with the rest of the code
1440-
LookupObject__c,
1460+
LookupObject__c,
14411461
LookupObject__r.QualifiedApiName,
1442-
CalcItem__c,
1462+
CalcItem__c,
14431463
CalcItem__r.QualifiedApiName,
14441464
RollupFieldOnCalcItem__c,
14451465
RollupFieldOnCalcItem__r.QualifiedApiName,
1446-
LookupFieldOnCalcItem__c,
1447-
LookupFieldOnCalcItem__r.QualifiedApiName,
1466+
LookupFieldOnCalcItem__c,
1467+
LookupFieldOnCalcItem__r.QualifiedApiName,
14481468
LookupFieldOnLookupObject__c,
14491469
LookupFieldOnLookupObject__r.QualifiedApiName,
14501470
RollupFieldOnLookupObject__c,
@@ -1675,7 +1695,7 @@ global without sharing virtual class Rollup implements Database.Batchable<SObjec
16751695
}
16761696

16771697
private static Boolean shouldRunFromTrigger() {
1678-
shouldRun = (shouldRun != null && shouldRun) || Trigger.isExecuting;
1698+
shouldRun = shouldRun || Trigger.isExecuting;
16791699
// in order to accomodate CDC; we set the apexContext manually there
16801700
// since technically all CDC is done from an AFTER_INSERT context
16811701
if (Trigger.operationType != null && isCDC == false) {
@@ -2072,7 +2092,9 @@ global without sharing virtual class Rollup implements Database.Batchable<SObjec
20722092
@testVisible
20732093
private virtual class DMLHelper {
20742094
public virtual void doUpdate(List<SObject> recordsToUpdate) {
2075-
update recordsToUpdate;
2095+
Database.DMLOptions dmlOptions = new Database.DMLOptions();
2096+
dmlOptions.AllowFieldTruncation = true;
2097+
Database.update(recordsToUpdate, dmlOptions);
20762098
}
20772099
}
20782100

rollup/main/default/classes/RollupTests.cls

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,36 @@ private class RollupTests {
506506
System.assertEquals(1, updatedAcc.NumberOfEmployees, 'COUNT_DISTINCT AFTER_INSERT should count regardless of not pointing to a field based on CMDT');
507507
}
508508

509+
@isTest
510+
static void shouldRunDirectlyFromApex() {
511+
Account acc = [SELECT Id FROM Account];
512+
513+
List<Opportunity> opps = new List<Opportunity>{
514+
new Opportunity(AccountId = acc.Id, Amount = 5),
515+
new Opportunity(AccountId = acc.Id, Amount = 10)
516+
};
517+
518+
Rollup.records = opps;
519+
Rollup.rollupMetadata = new List<Rollup__mdt>{
520+
new Rollup__mdt(
521+
RollupFieldOnCalcItem__c = 'Amount',
522+
LookupObject__c = 'Account',
523+
LookupFieldOnCalcItem__c = 'AccountId',
524+
LookupFieldOnLookupObject__c = 'Id',
525+
RollupFieldOnLookupObject__c = 'AnnualRevenue',
526+
RollupOperation__c = 'SUM',
527+
CalcItem__c = 'Opportunity'
528+
)
529+
};
530+
531+
Test.startTest();
532+
Rollup.runFromApex(opps, TriggerOperation.AFTER_INSERT);
533+
Test.stopTest();
534+
535+
acc = [SELECT AnnualRevenue FROM Account];
536+
System.assertEquals(15, acc.AnnualRevenue);
537+
}
538+
509539
/** Parent-initiated rollups */
510540
@isTest
511541
static void shouldAllowRollupToBeInitiatedFromTheParent() {
@@ -2562,6 +2592,20 @@ private class RollupTests {
25622592

25632593
/** Integration tests */
25642594

2595+
@isTest
2596+
static void shouldNotFailForTruncatedTextFields() {
2597+
Account acc = [SELECT Id FROM Account];
2598+
Opportunity opp = new Opportunity(AccountId = acc.Id, Description = '0'.repeat(256), Name = 'Truncate', StageName = 'Prospecting', CloseDate = System.today());
2599+
insert opp;
2600+
2601+
Test.startTest();
2602+
Rollup.performFullRecalculation('Description', 'AccountId', 'Id', 'Name', 'Account', 'Opportunity', 'CONCAT', null);
2603+
Test.stopTest();
2604+
2605+
acc = [SELECT Name FROM Account];
2606+
System.assertEquals(255, acc.Name.length(), acc.Name);
2607+
}
2608+
25652609
@isTest
25662610
static void shouldEnqueueFullRecalculationWhenBelowQueryLimits() {
25672611
Account acc = [SELECT Id FROM Account];

0 commit comments

Comments
 (0)