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

Added feature to rollup across related parent objects without needing to create intermediate rollups #28

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
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
29 changes: 29 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
version: 2
jobs:
deploy-prod:
docker:
- image: circleci/node:latest
steps:
- checkout
- run:
name: Install Dependencies
command: . build/install.sh
- run:
name: Login to Environment
command: . build/setup-prod.sh
- run:
name: Deploy to Production
command: . build/deploy-prod.sh
- run:
name: Run Local Test
command: . build/run-tests.sh

workflows:
version: 2
production-deployment:
jobs:
- deploy-prod:
filters:
branches:
only:
- master
Binary file added .sfdx/tools/apex.db
Binary file not shown.
3 changes: 3 additions & 0 deletions build/deploy-prod.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#Deploy the package to Prod
sf project convert source --api-version 58.0 --root-dir force-app --output-dir src
sf project deploy start --metadata-dir src --target-org prod-org --concise --ignore-conflicts
3 changes: 3 additions & 0 deletions build/install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
echo "Installing Dependencies... "
sudo npm install sfdx-cli --global
sudo npm install @salesforce/cli --global
1 change: 1 addition & 0 deletions build/run-tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sf apex run test --api-version 58.0 --target-org prod-org --test-level RunLocalTests --code-coverage --detailed-coverage --result-format junit --wait 30 > tests.xml
9 changes: 9 additions & 0 deletions build/setup-prod.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
echo "Setting up Org Connection..."
mkdir keys

echo $SFDC_CLIENT_ID
echo $SFDC_SERVER_KEY | base64 -d > keys/server.key

echo "Authenticating..."
sf org login jwt --username $SFDC_USERNAME --jwt-key-file keys/server.key --client-id $SFDC_CLIENT_ID --alias prod-org --set-default --instance-url https://login.salesforce.com
sf org list
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
public class LREngine {

/*
Tempalte tokens
Template tokens
0 : Fields to project
1 : Object to query
2 : Optional WHERE clause filter to add
Expand Down Expand Up @@ -126,9 +126,9 @@ public class LREngine {
}

// #0 token : SOQL projection
String soqlProjection = ctx.lookupField.getName();
String soqlProjection = ctx.lookupField!=NULL ? ctx.lookupField.getName() : ctx.relatedRelName;
List<String> orderByFields = new List<String>();
orderByFields.add(ctx.lookupField.getName()); // ensure details records are ordered by parent record
orderByFields.add(soqlProjection); // ensure details records are ordered by parent record

// k: detail field name, v: master field name
Integer exprIdx = 0;
Expand Down Expand Up @@ -180,7 +180,7 @@ public class LREngine {
}

// #3 Group by field
String grpByFld = ctx.lookupField.getName();
String grpByFld = ctx.lookupField!=NULL ? ctx.lookupField.getName() : ctx.relatedRelName;

// build approprite soql for this rollup context
String soql =
Expand Down Expand Up @@ -213,7 +213,13 @@ public class LREngine {
// Process Aggregate query results from RollupOperations related to Aggergate operations
List<AggregateResult> results = (List<AggregateResult>) queryResults;
for (AggregateResult res : results){
Id masterRecId = (Id)res.get(grpByFld);
Id masterRecId;
if(!grpByFld.contains('.'))
masterRecId = (Id)res.get(grpByFld);
else{
List<string> splitFields = grpByFld.split('\\.');
masterRecId = (Id)res.get(splitFields[splitFields.size()-1]);
}
Sobject masterObj = masterRecordsMap.get(masterRecId);
if (masterObj == null) {
System.debug(Logginglevel.WARN, 'No master record found for ID :' + masterRecId);
Expand All @@ -223,7 +229,6 @@ public class LREngine {
for (String alias : rsfByAlais.keySet()) {
RollupSummaryField rsf = rsfByAlais.get(alias);
Object aggregatedDetailVal = res.get(alias);
System.debug(LoggingLevel.INFO, 'New aggregarte value ' + aggregatedDetailVal + ' for master ' + masterRecId);
// Should also test for necessity
if(IsMultiCurrencyOrg() == true && rsf.isMasterTypeCurrency){
masterObj.put(rsf.master.getName(), convertCurrency((String)res.get(MASTERCURRENCYALIAS),(Decimal)aggregatedDetailVal));
Expand Down Expand Up @@ -478,6 +483,7 @@ public class LREngine {
public Schema.Sobjecttype detail;
// Lookup field on Child/Detail Sobject
public Schema.Describefieldresult lookupField;
public String relatedRelName;
// various fields to rollup on
public List<RollupSummaryField> fieldsToRoll;
// what type of rollups does this context contain
Expand All @@ -501,6 +507,21 @@ public class LREngine {
this.fieldsToRoll = new List<RollupSummaryField>();
}


public Context(Schema.Sobjecttype m, Schema.Sobjecttype d,
String relatedRelationShipName) {
this(m, d, relatedRelationShipName, '');
}

public Context(Schema.Sobjecttype m, Schema.Sobjecttype d,
String relatedRelationShipName, String detailWhereClause) {
this.master = m;
this.detail = d;
this.relatedRelName = relatedRelationShipName;
this.detailWhereClause = detailWhereClause;
this.fieldsToRoll = new List<RollupSummaryField>();
}

/**
Adds new rollup summary fields to the context
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>31.0</apiVersion>
<apiVersion>57.0</apiVersion>
<status>Active</status>
</ApexClass>
Original file line number Diff line number Diff line change
Expand Up @@ -784,5 +784,54 @@ private class TestLREngine {
System.assertEquals(2, masters.size());
System.assertEquals(expected1, reloadedAcc1.get(rollupField.master.getName()));
System.assertEquals(expected2, reloadedAcc2.get(rollupField.master.getName()));
}


/*
This test case uses standard objects Account, Contact and Contracts. An account can have one or more contacts and one contact can have one or more
contracts. The use case here is to rollup an object to n levels higher upto a grandparent or even higher upto 5 levels as permitted by
maximum number of related parent navigation in SOQL. Although contract also has a required relation with account but the idea is to show the use case

via the contract -> contact- > account and still use standard object in this generic test class

So if an account has 2 contacts and each contact has 2 contracts, then as an example , I can store 4 as the total number of contracts,
rolling upto the account level ,at a number field on the Account level
navigating via the Contact relationship and skipping intermediate rollup field creations.

This feature extends the rollup engine to support rollups on grandparents levels as well provided there is
a direct way to navigate via relationship fields (__r or otherwise)

The use case extendable to any other custom object hierarchy.
*/


static testMethod void testRollUpOnGrandParent(){
Account acc = new Account(Name='Test Acc');
insert acc;

Contact con1= new Contact(AccountId=acc.Id,LastName='TestL1');
Contact con2= new Contact(AccountId=acc.Id,LastName='TestL2');
insert new List<Contact>{con1,con2};

Contract c1 = new Contract(AccountId=acc.Id,CustomerSignedId = con1.Id,StartDate=Date.today(),Status='Draft',ContractTerm=4);
Contract c2 = new Contract(AccountId=acc.Id,CustomerSignedId = con1.Id,StartDate=Date.today(),Status='Draft',ContractTerm=5);
Contract c3 = new Contract(AccountId=acc.Id,CustomerSignedId = con2.Id,StartDate=Date.today(),Status='Draft',ContractTerm=5);
Contract c4 = new Contract(AccountId=acc.Id,CustomerSignedId = con2.Id,StartDate=Date.today(),Status='Draft',ContractTerm=5);

insert new List<Contract>{c1,c2,c3,c4};


LREngine.Context ctx = new LREngine.Context(Account.SobjectType,
Contract.SobjectType,
'CustomerSigned.AccountId'
);
ctx.add(
new LREngine.RollupSummaryField(
Schema.SObjectType.Account.fields.NumberOfEmployees, // just using a standard number field on account to test the feature.
Schema.SObjectType.Contract.fields.Id,
LREngine.RollupOperation.Count
));
acc=(Account)LREngine.rollUp(ctx, new Set<Id>{acc.Id})[0];
System.assertEquals(4, acc.NumberOfEmployees);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>31.0</apiVersion>
<apiVersion>57.0</apiVersion>
<status>Active</status>
</ApexClass>
10 changes: 10 additions & 0 deletions sfdx-project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"packageDirectories": [
{
"path": "force-app",
"default": true
}
],
"namespace": "",
"sourceApiVersion": "56.0"
}