Skip to content

Commit

Permalink
Added Row Limit feature
Browse files Browse the repository at this point in the history
#3
15
  • Loading branch information
afawcettffdc committed Jun 18, 2016
1 parent 8ab29d9 commit 8ccb38c
Show file tree
Hide file tree
Showing 16 changed files with 299 additions and 15 deletions.
15 changes: 12 additions & 3 deletions rolluptool/src/classes/CustomMetadataService.cls
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,20 @@ public class CustomMetadataService {
if(!dsr.isCustom())
continue;
Object fieldValue = customMetadataRecord.get(sObjectField);
if(fieldValue == null)
continue;
MetadataService.CustomMetadataValue cmdv = new MetadataService.CustomMetadataValue();
cmdv.field = dsr.getName();
cmdv.value = fieldValue+''; // TODO: More work here, type conversion
if(dsr.getType() == Schema.DisplayType.Double) {
if(fieldValue!=null) {
Decimal fieldValueNumber = (Decimal) fieldValue;
// TODO: Bit of a hack, MDT Number fields seem to be populated with zeros when the VF bound field is emptied by the user?!?
if(fieldValueNumber != 0) {
fieldValueNumber = fieldValueNumber.setScale(dsr.getScale());
cmdv.value = fieldValueNumber.format();
}
}
} else {
cmdv.value = fieldValue + ''; // TODO: More work here, type conversion
}
cm.values.add(cmdv);
}
return cm;
Expand Down
24 changes: 23 additions & 1 deletion rolluptool/src/classes/LREngine.cls
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,9 @@ public class LREngine {
rsf.operation == RollupOperation.Concatenate_Distinct) {
Concatenator concatenator =
new Concatenator(rsf.operation == RollupOperation.Concatenate_Distinct, rsf.concatenateDelimiter);
Integer rowIdx = 0;
for(SObject childDetailRecord : childDetailRecords) {
rowIdx++;
String childFieldValue = String.valueOf(childDetailRecord.get(rsf.detail.getName()));
if (childFieldValue != null) {
if (rsf.detail.getType() == Schema.DisplayType.MultiPicklist) {
Expand All @@ -289,6 +291,9 @@ public class LREngine {
concatenator.add(childFieldValue);
}
}
if(rsf.RowLimit!=null && rsf.RowLimit>0 && rowIdx == rsf.RowLimit) {
break;
}
}
String concatenatedValues = concatenator.toString();
concatenatedValues = concatenatedValues.abbreviate(rsf.master.getLength());
Expand All @@ -297,8 +302,13 @@ public class LREngine {
masterRecordsMap.get(masterId).put(
rsf.master.getName(), childDetailRecords[0].get(rsf.detail.getName()));
} else if(rsf.operation == RollupOperation.Last) {
Integer recordSetSize = childDetailRecords.size();
Integer index =
rsf.RowLimit!=null && rsf.RowLimit>0 ?
(rsf.RowLimit < recordSetSize ? rsf.RowLimit-1 : recordSetSize - 1) : recordSetSize - 1;
masterRecordsMap.get(masterId).put(
rsf.master.getName(), childDetailRecords[childDetailRecords.size()-1].get(rsf.detail.getName()));
rsf.master.getName(),
childDetailRecords[index].get(rsf.detail.getName()));
}
// Remove master Id record as its been processed
masterIds.remove(masterId);
Expand Down Expand Up @@ -380,6 +390,7 @@ public class LREngine {
public Schema.Describefieldresult detail;
public RollupOperation operation;
public String concatenateDelimiter;
public Integer rowLimit;

// derived fields, kept like this to save script lines later, by saving the same
// computations over and over again
Expand All @@ -402,10 +413,21 @@ public class LREngine {
Schema.Describefieldresult d,
RollupOperation op,
String concatenateDelimiter) {
this(m, d, op, concatenateDelimiter, null);
}


public RollupSummaryField(Schema.Describefieldresult m,
Schema.Describefieldresult d,
RollupOperation op,
String concatenateDelimiter,
Integer rowLimit) {

this.master = m;
this.detail = d;
this.operation = op;
this.concatenateDelimiter = concatenateDelimiter;
this.rowLimit = rowLimit;
// caching these derived attrbutes for once
// as their is no view state involved here
// and this caching will lead to saving in script lines later on
Expand Down
3 changes: 2 additions & 1 deletion rolluptool/src/classes/RollupService.cls
Original file line number Diff line number Diff line change
Expand Up @@ -1106,7 +1106,8 @@ global with sharing class RollupService
aggregateResultField.getDescribe(),
fieldToAggregate.getDescribe(),
RollupSummaries.OPERATION_PICKLIST_TO_ENUMS.get(lookup.AggregateOperation),
lookup.ConcatenateDelimiter);
lookup.ConcatenateDelimiter,
Integer.valueOf(lookup.RowLimit));

LookupRollupSummaryWrapper wrapper = new LookupRollupSummaryWrapper();
wrapper.Lookup = lookup;
Expand Down
127 changes: 127 additions & 0 deletions rolluptool/src/classes/RollupServiceTest.cls
Original file line number Diff line number Diff line change
Expand Up @@ -1314,6 +1314,133 @@ private with sharing class RollupServiceTest
System.assertEquals('Red;Yellow', (String) assertParents.get(parentC.id).get(aggregateResultField));
}


private testmethod static void testPicklistRollupWithLimits()
{
// Test supported?
if(!TestContext.isSupported())
return;

Schema.SObjectType parentType = LookupParent__c.sObjectType;
Schema.SObjectType childType = LookupChild__c.sObjectType;
String parentObjectName = parentType.getDescribe().getName();
String childObjectName = childType.getDescribe().getName();
String relationshipField = LookupChild__c.LookupParent__c.getDescribe().getName();
String aggregateField = LookupChild__c.Color__c.getDescribe().getName();
String aggregateResultField = LookupParent__c.Colours__c.getDescribe().getName();

// Create a picklist rollup
LookupRollupSummary__c rollupSummary = new LookupRollupSummary__c();
rollupSummary.Name = 'Test Rollup';
rollupSummary.ParentObject__c = parentObjectName;
rollupSummary.ChildObject__c = childObjectName;
rollupSummary.RelationShipField__c = relationshipField;
rollupSummary.FieldToAggregate__c = aggregateField;
rollupSummary.AggregateOperation__c = RollupSummaries.AggregateOperation.Concatenate.name();
rollupSummary.AggregateResultField__c = aggregateResultField;
rollupSummary.ConcatenateDelimiter__c = ';';
rollupSummary.Active__c = true;
rollupSummary.CalculationMode__c = 'Realtime';
rollupSummary.RowLimit__c = 2;
rollupSummary.AggregateAllRows__c = true;
insert rollupSummary;

// Insert parents
SObject parentA = parentType.newSObject();
parentA.put('Name', 'ParentA');
SObject parentB = parentType.newSObject();
parentB.put('Name', 'ParentB');
SObject parentC = parentType.newSObject();
parentC.put('Name', 'ParentC');
List<SObject> parents = new List<SObject> { parentA, parentB, parentC };
insert parents;

// Insert children
List<SObject> children = new List<SObject>();
for(SObject parent : parents)
{
String name = (String) parent.get('Name');
SObject child1 = childType.newSObject();
child1.put(relationshipField, parent.Id);
child1.put(aggregateField, 'Red');
children.add(child1);
SObject child2 = childType.newSObject();
child2.put(relationshipField, parent.Id);
child2.put(aggregateField, 'Yellow');
children.add(child2);
SObject child3 = childType.newSObject();
child3.put(relationshipField, parent.Id);
child3.put(aggregateField, 'Blue');
children.add(child3);
}
insert children;

// Assert rollups
Map<Id, SObject> assertParents = new Map<Id, SObject>(Database.query(String.format('select id, {0} from {1}', new List<String>{ aggregateResultField, parentObjectName })));
System.assertEquals('Red;Yellow', (String) assertParents.get(parentA.id).get(aggregateResultField));
System.assertEquals('Red;Yellow', (String) assertParents.get(parentB.id).get(aggregateResultField));
System.assertEquals('Red;Yellow', (String) assertParents.get(parentC.id).get(aggregateResultField));
}


private testmethod static void testLastRollupWithLimits()
{
// Test supported?
if(!TestContext.isSupported())
return;

Schema.SObjectType parentType = LookupParent__c.sObjectType;
Schema.SObjectType childType = LookupChild__c.sObjectType;
String parentObjectName = parentType.getDescribe().getName();
String childObjectName = childType.getDescribe().getName();
String relationshipField = LookupChild__c.LookupParent__c.getDescribe().getName();
String aggregateField = LookupChild__c.Color__c.getDescribe().getName();
String aggregateResultField = LookupParent__c.Colours__c.getDescribe().getName();

// Create a picklist rollup
LookupRollupSummary__c rollupSummary = new LookupRollupSummary__c();
rollupSummary.Name = 'Test Rollup';
rollupSummary.ParentObject__c = parentObjectName;
rollupSummary.ChildObject__c = childObjectName;
rollupSummary.RelationShipField__c = relationshipField;
rollupSummary.FieldToAggregate__c = aggregateField;
rollupSummary.AggregateOperation__c = RollupSummaries.AggregateOperation.Last.name();
rollupSummary.AggregateResultField__c = aggregateResultField;
rollupSummary.FieldToOrderBy__c = aggregateField + ' DESC';
rollupSummary.Active__c = true;
rollupSummary.CalculationMode__c = 'Realtime';
rollupSummary.RowLimit__c = 2;
rollupSummary.AggregateAllRows__c = true;
insert rollupSummary;

// Insert parents
SObject parent = parentType.newSObject();
parent.put('Name', 'ParentA');
List<SObject> parents = new List<SObject> { parent };
insert parents;

// Insert children
List<SObject> children = new List<SObject>();
String name = (String) parent.get('Name');
SObject child1 = childType.newSObject();
child1.put(relationshipField, parent.Id);
child1.put(aggregateField, '1');
children.add(child1);
SObject child2 = childType.newSObject();
child2.put(relationshipField, parent.Id);
child2.put(aggregateField, '2');
children.add(child2);
SObject child3 = childType.newSObject();
child3.put(relationshipField, parent.Id);
child3.put(aggregateField, '3');
children.add(child3);
insert children;

// Assert rollups
Map<Id, SObject> assertParents = new Map<Id, SObject>(Database.query(String.format('select id, {0} from {1}', new List<String>{ aggregateResultField, parentObjectName })));
System.assertEquals('2', (String) assertParents.get(parent.id).get(aggregateResultField));
}

private testmethod static void testLimitsConsumedWithSingleChildChanged()
{
// Test supported?
Expand Down
17 changes: 15 additions & 2 deletions rolluptool/src/classes/RollupSummaries.cls
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,20 @@ public class RollupSummaries extends fflib_SObjectDomain
lookupRollupSummary.Fields.RelationshipCriteriaFields.addError(error('Field ' + fieldsInError[0] + ' does not exist on the child object.', lookupRollupSummary.Record, LookupRollupSummary__c.RelationshipCriteriaFields__c));
else if(fieldsInError.size()>1)
lookupRollupSummary.Fields.RelationshipCriteriaFields.addError(error('Fields ' + String.join(fieldsInError, ',') + ' do not exist on the child object.', lookupRollupSummary.Record, LookupRollupSummary__c.RelationshipCriteriaFields__c));
}
}
// Row limit is only supported for certain operations
LREngine.RollupOperation operation =
OPERATION_PICKLIST_TO_ENUMS.get(lookupRollupSummary.AggregateOperation);
if(operation!=null && lookupRollupSummary.RowLimit!=null) {
Set<LREngine.RollupOperation> operationsSupportingRowLimit
= new Set<LREngine.RollupOperation>{
LREngine.RollupOperation.Last,
LREngine.RollupOperation.Concatenate,
LREngine.RollupOperation.Concatenate_Distinct };
if(!operationsSupportingRowLimit.contains(operation)) {
lookupRollupSummary.Fields.RowLimit.addError(error('Row Limit is only supported on Last and Concatentate operators.', lookupRollupSummary.Record, LookupRollupSummary__c.RowLimit__c ));
}
}
try
{
// If all objects and fields valid...
Expand All @@ -313,7 +326,7 @@ public class RollupSummaries extends fflib_SObjectDomain
new LREngine.RollupSummaryField(
aggregateResultField.getDescribe(),
fieldToAggregate.getDescribe(),
OPERATION_PICKLIST_TO_ENUMS.get(lookupRollupSummary.AggregateOperation),
operation,
lookupRollupSummary.ConcatenateDelimiter));
// Validate the SOQL
if(lookupRollupSummary.RelationShipCriteria!=null &&
Expand Down
6 changes: 4 additions & 2 deletions rolluptool/src/classes/RollupSummariesSelector.cls
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ public class RollupSummariesSelector
LookupRollupSummary__c.CalculationSharingMode__c,
LookupRollupSummary__c.TestCode__c,
LookupRollupSummary__c.TestCodeSeeAllData__c,
LookupRollupSummarY__c.AggregateAllRows__c
LookupRollupSummary__c.AggregateAllRows__c,
LookupRollupSummary__c.RowLimit__c
};
}

Expand Down Expand Up @@ -228,7 +229,8 @@ public class RollupSummariesSelector
LookupRollupSummary2__mdt.TestCode__c,
LookupRollupSummary2__mdt.TestCodeSeeAllData__c,
LookupRollupSummary2__mdt.Description__c,
LookupRollupSummary2__mdt.AggregateAllRows__c
LookupRollupSummary2__mdt.AggregateAllRows__c,
LookupRollupSummary2__mdt.RowLimit__c
};
}

Expand Down
25 changes: 25 additions & 0 deletions rolluptool/src/classes/RollupSummariesTest.cls
Original file line number Diff line number Diff line change
Expand Up @@ -517,4 +517,29 @@ private class RollupSummariesTest
System.assertEquals(0, fflib_SObjectDomain.Errors.getAll().size());
}


private testmethod static void testUseOfRowLimitOnSum()
{
// Test supported?
if(!TestContext.isSupported())
return;

LookupRollupSummary__c rollupSummary = new LookupRollupSummary__c();
rollupSummary.Name = 'Total Opportunities into Annual Revenue on Account';
rollupSummary.ParentObject__c = 'Account';
rollupSummary.ChildObject__c = 'Opportunity';
rollupSummary.RelationShipField__c = 'AccountId';
rollupSummary.RelationShipCriteria__c = null;
rollupSummary.FieldToAggregate__c = 'Amount';
rollupSummary.AggregateOperation__c = 'Sum';
rollupSummary.AggregateResultField__c = 'AnnualRevenue';
rollupSummary.RowLimit__c = 10;
rollupSummary.Active__c = true;
rollupSummary.CalculationMode__c = 'Realtime';
fflib_SObjectDomain.Test.Database.onInsert(new LookupRollupSummary__c[] { rollupSummary } );
fflib_SObjectDomain.triggerHandler(RollupSummaries.class);
System.assertEquals(1, fflib_SObjectDomain.Errors.getAll().size());
System.assertEquals('Row Limit is only supported on Last and Concatentate operators.', fflib_SObjectDomain.Errors.getAll()[0].message);
System.assertEquals(LookupRollupSummary__c.RowLimit__c, ((fflib_SObjectDomain.FieldError)fflib_SObjectDomain.Errors.getAll()[0]).field);
}
}
10 changes: 10 additions & 0 deletions rolluptool/src/classes/RollupSummary.cls
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,11 @@ public class RollupSummary {
set { Record.put('AggregateAllRows__c', value); }
}

public Decimal RowLimit {
get { return (Decimal) Record.get('RowLimit__c'); }
set { Record.put('RowLimit__c', value); }
}

public void addError(String errorMessage) {

// Store the error message
Expand Down Expand Up @@ -208,6 +213,7 @@ public class RollupSummary {
public final FieldData TestCode = new FieldData(this);
public final FieldData TestCodeSeeAllData = new FieldData(this);
public final FieldData AggregateAllRows = new FieldData(this);
public final FieldData RowLimit = new FieldData(this);
}

/**
Expand Down Expand Up @@ -261,6 +267,8 @@ public class RollupSummary {
fieldLabelInError = LookupRollupSummary__c.TestCodeSeeAllData__c.getDescribe().getLabel();
} else if(this === RecordMetadata.AggregateAllRows) {
fieldLabelInError = LookupRollupSummary__c.AggregateAllRows__c.getDescribe().getLabel();
} else if(this === RecordMetadata.RowLimit) {
fieldLabelInError = LookupRollupSummary__c.RowLimit__c.getDescribe().getLabel();
}

// Store error
Expand Down Expand Up @@ -308,6 +316,8 @@ public class RollupSummary {
customObjectRecord.TestCodeSeeAllData__c.addError(errorMessage);
} else if(this === RecordMetadata.AggregateAllRows) {
customObjectRecord.AggregateAllRows__c.addError(errorMessage);
} else if(this === RecordMetadata.RowLimit) {
customObjectRecord.RowLimit__c.addError(errorMessage);
}
}
}
Expand Down
23 changes: 23 additions & 0 deletions rolluptool/src/classes/TestLREngine.cls
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,17 @@ private class TestLREngine {
'Lost,Won,Won');
}

static testMethod void testRollupConcatenateLimited() {
testRollup(
Schema.SObjectType.Opportunity.fields.StageName.getName(),
new LREngine.RollupSummaryField(
Schema.SObjectType.Account.fields.Description,
Schema.SObjectType.Opportunity.fields.StageName,
LREngine.RollupOperation.Concatenate, ',', 2),
'test,test',
'Lost,Won');
}

static testMethod void testRollupConcatenateDeletedChildRows() {
testRollup(
Schema.SObjectType.Opportunity.fields.StageName.getName(),
Expand Down Expand Up @@ -1054,6 +1065,17 @@ private class TestLREngine {
'Lost');
}

static testMethod void testRollupLastLimit() {
testRollup(
Schema.SObjectType.Opportunity.fields.Amount.getName(),
new LREngine.RollupSummaryField(
Schema.SObjectType.Account.fields.Description,
Schema.SObjectType.Opportunity.fields.StageName,
LREngine.RollupOperation.Last, null, 2),
'test',
'Won');
}

static testMethod void testMultipleRollupsSameResultField() {
prepareData();

Expand Down Expand Up @@ -1116,6 +1138,7 @@ private class TestLREngine {
}

static private void testRollup(String detailOrderByClause, LREngine.RollupSummaryField rollupField, String expected1, String expected2, boolean allRows) {

prepareData();

if(allRows)
Expand Down
Loading

0 comments on commit 8ccb38c

Please sign in to comment.