function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
tsalbtsalb 

Apex Rollup Summary Trigger - more than one Sum in a map?

I've leveraged the trigger example here: http://www.anthonyvictorio.com/salesforce/roll-up-summary-trigger/ however I need to change it so that it can accomodate for 4 sum of currency fields (not just 1) to update four different rollup fields on the parent Account (Bank__c).

 

Some information: A Bank has multiple SRFs, and under each SRF are a set of Fees. There are 4 Fee fields on the SRFs that each need to roll up seperately onto their respective Fee fields on the Bank. That's why there is a Pipeline_Fees_Bank__c and Pipeline_Fees__c (SRF). There are 3 more sets of these fields.

 

How can I achieve rolling up the other three by modifying this?

 

trigger rollUpFees on Service_Request__c (after delete, after insert, after update) {

  //Limit the size of list by using Sets which do not contain duplicate elements
  set<Id> AccountIds = new set<Id>();

  //When adding new SRFs or updating existing SRFs
  if(trigger.isInsert || trigger.isUpdate){
    for(Service_Request__c p : trigger.new){
      AccountIds.add(p.Bank__c);
    }
  }

  //When deleting SRFs
  if(trigger.isDelete){
    for(Service_Request__c p : trigger.old){
      AccountIds.add(p.Bank__c);
    }
  }

  //Map will contain one Bank Id to one sum value
  map<Id,Double> AccountMap = new map <Id,Double>();

  //Produce a sum of fees on SRFs and add them to the map
  //use group by to have a single Bank Id with a single sum value
  for(AggregateResult q : [select Bank__c,sum(Pipeline_Fees__c)
    from Service_Request__c where Bank__c IN :AccountIds group by Bank__c]){
      AccountMap.put((Id)q.get('Bank__c'),(Double)q.get('expr0'));
  }

  List<Account> AccountsToUpdate = new List<Account>();

  //Run the for loop on Accounts using the non-duplicate set of Bank Ids
  //Get the sum value from the map and create a list of Accounts to update
  for(Account a : [Select Id, Pipeline_Fees_Bank__c from Account where Id IN :AccountIds]){
    Double PaymentSum = AccountMap.get(a.Id);
    a.Pipeline_Fees_Bank__c = PaymentSum;
    AccountsToUpdate.add(a);
  }

  update AccountsToUpdate;
}

 

To get an idea of what I'd like to change...There are 3 more "Fees" that need to be summed up:

 

  //Produce a sum of fees on SRFs and add them to the map
  //use group by to have a single Bank Id with a single sum value
  for(AggregateResult q : [select Bank__c,sum(Pipeline_Fees__c),sum(Incurred_Fees__c),sum(Paid_Fees__c),sum(Unpaid_Fees__c)
    from Service_Request__c where Bank__c IN :AccountIds group by Bank__c]){
      AccountMap.put((Id)q.get('Bank__c'),(Double)q.get('expr0'));
  }

 I'm new to triggers, so I'm not sure how to achieve this! I don't want to be writing four triggers, one for each one - i dont think that's the best way to achieve this...

Best Answer chosen by Admin (Salesforce Developers) 
SrikanthKuruvaSrikanthKuruva

you will have to do the following changes in the code.

 

//Map will contain one Bank Id to one sum value
  map<Id,Double> AccountMap = new map <Id,Double>();
map<Id,Double> AccountMapIncurred = new map <Id,Double>();//change
map<Id,Double> AccountMapPaid = new map <Id,Double>();//change
map<Id,Double> AccountMapUnpaid = new map <Id,Double>();//change

  //Produce a sum of fees on SRFs and add them to the map
  //use group by to have a single Bank Id with a single sum value
  for(AggregateResult q : [select Bank__c,sum(Pipeline_Fees__c),sum(Incurred_Fees__c),sum(Paid_Fees__c),sum(Unpaid_Fees__c)
    from Service_Request__c where Bank__c IN :AccountIds group by Bank__c]){
      AccountMap.put((Id)q.get('Bank__c'),(Double)q.get('expr0'));
AccountMapIncurred.put((Id)q.get('Bank__c'),(Double)q.get('expr1'));//change
AccountMapPaid.put((Id)q.get('Bank__c'),(Double)q.get('expr2'));//change
AccountMapUnpaid.put((Id)q.get('Bank__c'),(Double)q.get('expr3'));//change
  }

List<Account> AccountsToUpdate = new List<Account>();

  //Run the for loop on Accounts using the non-duplicate set of Bank Ids
  //Get the sum value from the map and create a list of Accounts to update
  for(Account a : [Select Id, Pipeline_Fees_Bank__c from Account where Id IN :AccountIds]){
    Double PaymentSum = AccountMap.get(a.Id);
    a.Pipeline_Fees_Bank__c = PaymentSum;
a.Incurred_Fees__c = AccountMapIncurred.get(a.Id);//change
a.Paid_Fees__c = AccountMapPaid.get(a.Id);//change
a.Unpaid_Fees__c = AccountMapUnpaid.get(a.Id);//change
    AccountsToUpdate.add(a);
  }

  update AccountsToUpdate;
}

 

All Answers

SrikanthKuruvaSrikanthKuruva

I want to ask you a question here 

what is the relation between Account object and Service_Request__c. is it a Master-Detail relationship or just a lookup relationship? Because you dont need a trigger in case if its a Master-Detail relation.

 

tsalbtsalb
Its a lookup relationship - I would have used point and click configuration if I could have!
SrikanthKuruvaSrikanthKuruva

you will have to do the following changes in the code.

 

//Map will contain one Bank Id to one sum value
  map<Id,Double> AccountMap = new map <Id,Double>();
map<Id,Double> AccountMapIncurred = new map <Id,Double>();//change
map<Id,Double> AccountMapPaid = new map <Id,Double>();//change
map<Id,Double> AccountMapUnpaid = new map <Id,Double>();//change

  //Produce a sum of fees on SRFs and add them to the map
  //use group by to have a single Bank Id with a single sum value
  for(AggregateResult q : [select Bank__c,sum(Pipeline_Fees__c),sum(Incurred_Fees__c),sum(Paid_Fees__c),sum(Unpaid_Fees__c)
    from Service_Request__c where Bank__c IN :AccountIds group by Bank__c]){
      AccountMap.put((Id)q.get('Bank__c'),(Double)q.get('expr0'));
AccountMapIncurred.put((Id)q.get('Bank__c'),(Double)q.get('expr1'));//change
AccountMapPaid.put((Id)q.get('Bank__c'),(Double)q.get('expr2'));//change
AccountMapUnpaid.put((Id)q.get('Bank__c'),(Double)q.get('expr3'));//change
  }

List<Account> AccountsToUpdate = new List<Account>();

  //Run the for loop on Accounts using the non-duplicate set of Bank Ids
  //Get the sum value from the map and create a list of Accounts to update
  for(Account a : [Select Id, Pipeline_Fees_Bank__c from Account where Id IN :AccountIds]){
    Double PaymentSum = AccountMap.get(a.Id);
    a.Pipeline_Fees_Bank__c = PaymentSum;
a.Incurred_Fees__c = AccountMapIncurred.get(a.Id);//change
a.Paid_Fees__c = AccountMapPaid.get(a.Id);//change
a.Unpaid_Fees__c = AccountMapUnpaid.get(a.Id);//change
    AccountsToUpdate.add(a);
  }

  update AccountsToUpdate;
}

 

This was selected as the best answer
SrikanthKuruvaSrikanthKuruva

let me know if you face any issue with that

tsalbtsalb

Thank you so much. Worked perfectly.

tsalbtsalb

Having problems with my test class though....borrowed it from the link on the first post.

 

Pipeline_Fees__c on Service Requests (p1.Pipeline_Fees__c) is a formula field... i was reading that you needed to insert or update the record before formulas calculated. Order_Fees__c is a currency field that changes the Pipeline Fees formula. 

 

Pipeline_Fees_Bank__c on the Account (a.Pipeline_Fees_Bank__c is a currency field). The trigger works great, but this test class is failing on the assert:

 

Assertion Failed: Expected 0.00, Actual: null - which i think is saying the Pipeline_Fees__c is null. 

 

Where am i going wrong here?

 

trigger rollUpFees on Service_Request__c (after delete, after insert, after update) {

  //Limit the size of list by using Sets which do not contain duplicate elements
  set<Id> AccountIds = new set<Id>();

  //When adding new SRFs or updating existing SRFs
  if(trigger.isInsert || trigger.isUpdate){
    for(Service_Request__c p : trigger.new){
      AccountIds.add(p.Bank__c);
    }
  }

  //When deleting SRFs
  if(trigger.isDelete){
    for(Service_Request__c p : trigger.old){
      AccountIds.add(p.Bank__c);
    }
  }

  //Map will contain one Bank Id to one sum value
  map<Id,Double> AccountMapPipeline = new map <Id,Double>();
  map<Id,Double> AccountMapIncurred = new map <Id,Double>();
  map<Id,Double> AccountMapPaid = new map <Id,Double>();
  map<Id,Double> AccountMapUnpaid = new map <Id,Double>();


  //Produce a sum of fees on SRFs and add them to the map
  //use group by to have a single Bank Id with a single sum value
  for(AggregateResult q : [select Bank__c,sum(Pipeline_Fees__c),sum(Incurred_Fees__c),sum(Paid_Fees__c),sum(Unpaid_Fees__c)
    from Service_Request__c where Bank__c IN :AccountIds group by Bank__c]){
      AccountMapPipeline.put((Id)q.get('Bank__c'),(Double)q.get('expr0'));
	  AccountMapIncurred.put((Id)q.get('Bank__c'),(Double)q.get('expr1'));
	  AccountMapPaid.put((Id)q.get('Bank__c'),(Double)q.get('expr2'));
	  AccountMapUnpaid.put((Id)q.get('Bank__c'),(Double)q.get('expr3'));
  }

  List<Account> AccountsToUpdate = new List<Account>();

  //Run the for loop on Accounts using the non-duplicate set of Bank Ids
  //Get the sum value from the map and create a list of Accounts to update
  for(Account a : [Select Id, Pipeline_Fees_Bank__c from Account where Id IN :AccountIds]){
    Double PipelineSum = AccountMapPipeline.get(a.Id);
	Double IncurredSum = AccountMapIncurred.get(a.Id);
	Double PaidSum = AccountMapPaid.get(a.Id);
	Double UnpaidSum = AccountMapUnpaid.get(a.Id);
    a.Pipeline_Fees_Bank__c = PipelineSum;
	a.Incurred_Fees_Bank__c = IncurredSum;
    a.Paid_Fees_Bank__c = PaidSum;
    a.Unpaid_Fees_Bank__c = UnpaidSum;
    AccountsToUpdate.add(a);
  }

  update AccountsToUpdate;
}

 

 

@isTest
private class TestrollUpFees {

    static testMethod void myUnitTest() {

        Profile pf = [Select Id from Profile where Name = 'System Administrator'];

        User u = new User();
        u.FirstName = 'Test';
        u.LastName = 'User';
        u.Email = 'testuser@test123456789.com';
        u.CompanyName = 'test.com';
        u.Title = 'Test User';
        u.Username = 'testuser@test123456789.com';
        u.Alias = 'testuser';
        u.CommunityNickname = 'Test User';
        u.TimeZoneSidKey = 'America/Mexico_City';
        u.LocaleSidKey = 'en_US';
        u.EmailEncodingKey = 'ISO-8859-1';
        u.ProfileId = pf.Id;
        u.LanguageLocaleKey = 'en_US';
        insert u;

        system.runAs(u){

            Account a = new Account();
            a.Name = 'Test Account';
            a.LIN__c = '1234';
            a.Status__c = 'Confirmed';
	    a.Type = 'Other';
	    a.Bank_Fin__c = '1234';
            insert a;
            
            system.assertEquals(a.Pipeline_Fees_Bank__c, null);
            
            Task_Order__c t = new Task_Order__c();
            t.Name = 'Test Task Order';
	    insert t;	

            //Test payments on insert
            Service_Request__c p1 = new Service_Request__c();
            p1.Task_Order__c = t.Id;
            p1.Bank__c = a.Id;
            p1.Status__c = 'New';
            insert p1;
            p1.Order_Fee__c = 100;
            update p1;

            Account ou1 = [select Pipeline_Fees_Bank__c from Account where Id = :a.Id];
            system.assertEquals(ou1.Pipeline_Fees_Bank__c,p1.Pipeline_Fees__c);      //Assertion Failed: Expected 0.00, Actual: null

            //Test payments on update
            Service_Request__c p1u = [select Order_Fee__c from Service_Request__c where Id = :p1.Id];
            p1u.Order_Fee__c = 200;
            update p1u;

            Account ou2 = [select Pipeline_Fees_Bank__c from Account where Id = :a.Id];
            system.assertEquals(ou2.Pipeline_Fees_Bank__c,p1u.Order_Fee__c);

            //Test payments on second insert
            Service_Request__c p2 = new Service_Request__c();
            p2.Bank__c = a.Id;
            p2.Order_Fee__c = 800;
            insert p2;

            AggregateResult ag1 = [select sum(Order_Fee__c) from Service_Request__c where Bank__c = :a.Id];

            Account ou3 = [select Pipeline_Fees_Bank__c from Account where Id = :a.Id];
            system.assertEquals(ou3.Pipeline_Fees_Bank__c,ag1.get('expr0'));

            //Test payment on delete
            delete p2;

            AggregateResult ag2 = [select sum(Order_Fee__c) from Service_Request__c where Bank__c = :a.Id];

            Account ou4 = [select Pipeline_Fees_Bank__c from Account where Id = :a.Id];
            system.assertEquals(ou4.Pipeline_Fees_Bank__c,ag2.get('expr0'));

        }

    }

}

 

tsalbtsalb

Still pretty lost on the test class...

Amit Singh1989Amit Singh1989

Hi SrikanthKuruva ,

 

I need to handle similar kind of scenerio, and it is working well with the help of Trigger except if I change master of child, amound is not deducted from old parent.

 

Two objects are there 

1)Job

2)Campaign

 

Campaign is master of Job in lookup relationship and I want a field (like Rollup Summary) which will take sum of related jobs Amount.

 

eg.


Camp1 --

Job 1 -- amount = 10

Job 2 -- amount = 15

Job 3 -- amount= 20

 

so on campaign amount will be 45

 

but if i change the Campaign of Job 1 from Camp1 to another Campaign then its amount should be deducted from Camp1,

but this is not happening with my trigger,

 

Please help me on this,


here is my Trigger


trigger UpdateCampaignsAmount on Job__c (after delete, after insert, after undelete, 
after update, before delete, before insert, before update) 
{
	//Use Set to Retrieve ID of Campaigns
	Set<ID> CampIDs = new Set<ID>();
	
	//When adding new Job or updating existing Job
	if(Trigger.isInsert || Trigger.isUpdate)
	 {
	 	for(Job__c job : Trigger.New)
	 	{
	 	 CampIDs.add(job.Campaign__c);
		 /*********Fetch the Old Record's Campaign***********/
		 if(Trigger.isUpdate)
			CampIDs.add(Trigger.oldMap.get(job.Id).Campaign__c);	
	 	}
	 }
	 
	 //When Deleting any Job
	 if(Trigger.isDelete)
	 {
	 	for(Job__c job: Trigger.Old)
	 	{
	 		CampIDs.add(job.Campaign__c);
	 	}
	 }
	 
	 //Map will contain one Campaign id to one sum value
	 Map<Id,Double> CampMap = new Map<Id,Double>();
	 
	 //Produce Sum of Invoices and add them to the MAP
	 //Use Group By to have a single Campaign ID with a single sum value
	 for(AggregateResult ar : [select Campaign__c, sum(Invoice_Actual_Amounts__c) from Job__c where Campaign__c IN: CampIDs group by Campaign__c])
	 {
	 	CampMap.put(String.valueOf(ar.get('Campaign__c')),Double.valueOf((ar.get('expr0') == null)? 0 : ar.get('expr0')));	 	
	 }
	 
	 List<Campaign__c> CampaignToUpdate = new List<Campaign__c>();
	 
	
	
	 for(Id campId: CampMap.keySet())
	 {
		CampaignToUpdate.add(new Campaign__c(Id = campId, Actual_Cost__c = CampMap.get(campId)));
	 }
	 update CampaignToUpdate;

}