Sample Code: Custom Roll-Up Summary

14 Sep

As any Salesforce developer knows, if you want to create a field that “rolls up” a child records’ amount to its master object, you can simply create a Rollup Summary field.  But what if the relationship between the 2 objects isn’t a master-detail relationship, but a lookup relationship?  If it’s a lookup relationship, native Salesforce functionality won’t allow you to roll up any fields from one record to another.

This is a situation that will require custom code .

In my code sample, I have an Opportunity with a lookup field that allows the user to select a Portfolio record.  Each time the Opportunity amount changes, it should also trigger a change on its corresponding Portfolio record- to be more specific, it should trigger a change on the ‘Transaction Amount’ field on Portfolio.  The ‘Transaction Amount’ field calculates the total amount of all its associated Opportunity amounts.

The Portfolio page layout has an Opportunity related list that shows all the opportunities that look up to that one Portfolio.  We have to create a trigger for this because this is a ‘custom roll-up summary’ (‘rolling up’ to the Portfolio detail page) and as such requires a custom trigger, Apex class, and a test class.

 

/** TRIGGER Description: Custom roll-up summary of oppty amounts to Transaction_Amount__c on portfolio **/

trigger opportunityTrigger on Opportunity (before insert, before update, after insert, after update, after delete, after undelete) {

 

// other trigger logic here – note that it’s best practice to use a trigger template for each object

// sample trigger template 1 and sample trigger template 2

 

if (Trigger.isAfter && (Trigger.isInsert || Trigger.isUpdate || Trigger.isDelete || Trigger.isUndelete)) {

 

Set<Id> portfolioIds = new Set<Id>();

 

// add portfolio ids coming from new data

if (Trigger.new != null) {

for (Opportunity o : Trigger.new) {

 

// only add opps with valid portfolio id

if (o.Portfolio__c != null) {

portfolioIds.add(o.Portfolio__c);

}

}

}

 

// add portfolio ids coming from old data (deletes, moving an opp from one portfolio to another)

if (Trigger.old != null) {

for (Opportunity o : Trigger.old) {

 

// only add opps with valid portfolio id

if (o.Portfolio__c != null) {

portfolioIds.add(o.Portfolio__c);

}

}

}

 

if (portfolioIds.size() > 0) {

TransAmtRollUp.calculateTransAmt(portfolioIds);

}

 

}

}

 

 

/** APEX Class: TransAmtRollUp **/

 

public with sharing class TransAmtRollUp {

 

public static void calculateTransAmt (Set<Id> portfolioIds) {

 

// stores all portfolio Ids that have totals

Set<Id> IdsWithTotals = new Set<Id>();

 

// stores each portfolio id and its total opportunity amount

Map<Id,Double> oppTotals = new Map<Id,Double>();

 

AggregateResult[] groupedPortfolio = [ SELECT Portfolio__c, SUM(Amount) FROM Opportunity WHERE Portfolio__c IN :portfolioIds

GROUP BY Portfolio__c ];

 

for (AggregateResult ar : groupedPortfolio) {

IdsWithTotals.add((String)ar.get(‘Portfolio__c’)); // add each portfolio id with totals

opptotals.put((Id)ar.get(‘Portfolio__c’), (Double)ar.get(‘expr0’)); // add each portfolio id and its total amount

}

 

// put all portfolio with totals into a List of SObjects

List<Portfolio__c> portfolioToUpdate = [ SELECT Id, Name, Transaction_Amount__c FROM Portfolio__c WHERE Id IN :IdsWithTotals ];

 

// loop through the list and update the total for each Portfolio__c by looking up the total from oppTotals Map

for (Portfolio__c p : portfolioToUpdate) {

p.Transaction_Amount__c = oppTotals.get(p.id);

}

 

update portfolioToUpdate;

 

}

}

 

/** Write your own TEST CLASS: (OpportunityTriggerHandler_Test.cls) **/

Leave a comment