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
Amanda JonesAmanda Jones 

trigger doesn't recalculate when change made to record

I have what I think is a quick question about fixing a trigger that I've written. 

The total donations are being calculated in a currency field on the Campaigns object. The problem is that when I delete one of the donations, the field does not recalculate to show the reduced amount.

How do I need to change my code to make this happen? 

Thanks in advance for your help!

Here is my code:

/* **********************************************************************************
 *
 * Trigger: Total Amount Received for Campaign Rollup
 * Created by:Amanda Jones
 *
 * Purpose/Methods:
 * - This trigger rolls up all of the Donations (Opportunities) into a
 * - currency field on a Campaign. It is executed after an insert or an update of
 * - opportunity
 *
 * Unit Test:
 * - TEST_TotalAmountReceived Apex Class
 *
 ************************************************************************************** */
 
trigger TotalAmountReceivedforCampaign on Opportunity (after insert, after update) {
 
  // gather campaigns from Opps being updated
  List<String> campIds = new List<String>();
 
  for (Opportunity o : trigger.new){
   if (o.CampaignID != null && (trigger.isInsert || o.Amount != trigger.oldMap.get(o.id).Amount))
   campIds.add(o.CampaignId);
  }
 
  if (campIds.size() > 0) {
 
  Map<id, Campaign> campaigns = new Map<id, Campaign>([SELECT id FROM Campaign WHERE id =: campIds]);
 
  // initialize Campaign.Total_Amount_Received__c to zero on all campaigns
  for (Campaign c : campaigns.values())
   c.Total_Amount_Received__c= 0;
 
  // add all Opp.Amount_Received__c to campaigns
  for (Opportunity o : [SELECT id, Amount, CampaignId FROM Opportunity WHERE CampaignId =: campIds]){
   Campaign c = campaigns.get(o.CampaignId);
   c.Total_Amount_Received__c += o.Amount;
  }
 
  // update campaigns
  update campaigns.values();
  }
}
Best Answer chosen by Amanda Jones
Amit Chaudhary 8Amit Chaudhary 8
Please try below code in trigger :-
trigger TotalAmountReceivedforCampaign on Opportunity (after insert, after update , After delete ) 
{
 
  // gather campaigns from Opps being updated
  List<String> campIds = new List<String>();
  List<String> campIdRemoved = new List<String>();

	if(Trigger.isInsert || Trigger.isUpdate)
	{
		for (Opportunity o : trigger.new)
		{
			if (o.CampaignID != null && (trigger.isInsert || o.Amount != trigger.oldMap.get(o.id).Amount))
				campIds.add(o.CampaignId);
		}
	}
	else if (Trigger.isDelete)
	{
		for (Opportunity o : trigger.old)
		{
			if ( o.CampaignID != null )
				campIds.add(o.CampaignId);
		}
	}	
 
  if (campIds.size() > 0) 
  {
 
	  Map<id, Campaign> campaigns = new Map<id, Campaign>([SELECT id FROM Campaign WHERE id =: campIds]);
	 
	  // initialize Campaign.Total_Amount_Received__c to zero on all campaigns
	  for (Campaign c : campaigns.values())
	   c.Total_Amount_Received__c= 0;
	 
	  // add all Opp.Amount_Received__c to campaigns
		for (Opportunity o : [SELECT id, Amount, CampaignId FROM Opportunity WHERE CampaignId =: campIds])
		{
			Campaign c = campaigns.get(o.CampaignId);
			c.Total_Amount_Received__c += o.Amount;
		}
 
	// update campaigns
	update campaigns.values();
  }
  
}

And try below Test class:-
@isTest
 private class TEST_TotalAmountReceived {
 
static testMethod void testTotalAmountReceived() 
{
 
	// Create a test campaign
	Campaign c = new Campaign ();
	c.Name = 'UnitTest';
	insert c;
	System.assert(c != null);
	 
	// Create a test opportunity for the campaign
	Opportunity o = new Opportunity ();
	o.Name = 'UnitTest';
	o.StageName = 'Closed Won';
	o.CloseDate = Date.Today();
	o.CampaignID = c.ID;
	o.Amount = 70.00;
	insert o;
	System.assert(o != null);
	  
	// Retrieve the Campaign
	Campaign c1 = [SELECT Total_Amount_Received__c FROM Campaign WHERE Id = :c.Id];
	System.assertEquals (70.00, c1.Total_Amount_Received__c);

	Delete o;
}
}

Please let us know if this will help you


 

All Answers

Amit Chaudhary 8Amit Chaudhary 8
Pleas try below . I hope that will help you
trigger TotalAmountReceivedforCampaign on Opportunity (after insert, after update , before delete ) 
{
 
  // gather campaigns from Opps being updated
  List<String> campIds = new List<String>();
  List<String> campIdRemoved = new List<String>();

	if(Trigger.isInsert || Trigger.isUpdate)
	{
		for (Opportunity o : trigger.new)
		{
			if (o.CampaignID != null && (trigger.isInsert || o.Amount != trigger.oldMap.get(o.id).Amount))
				campIds.add(o.CampaignId);
		}
	}
	else if (Trigger.isDelete)
	{
		for (Opportunity o : trigger.old)
		{
			if ( o.CampaignID != null )
				campIds.add(o.CampaignId);
		}
	}	
 
  if (campIds.size() > 0) 
  {
 
	  Map<id, Campaign> campaigns = new Map<id, Campaign>([SELECT id FROM Campaign WHERE id =: campIds]);
	 
	  // initialize Campaign.Total_Amount_Received__c to zero on all campaigns
	  for (Campaign c : campaigns.values())
	   c.Total_Amount_Received__c= 0;
	 
	  // add all Opp.Amount_Received__c to campaigns
		for (Opportunity o : [SELECT id, Amount, CampaignId FROM Opportunity WHERE CampaignId =: campIds])
		{
			Campaign c = campaigns.get(o.CampaignId);
			c.Total_Amount_Received__c += o.Amount;
		}
 
	// update campaigns
	update campaigns.values();
  }
  
}

Please mark this as solution if that will help you. So that is some one has same issue this post can help other.

Thanks
AMit Chaudhary
amit.salesforce21@gmail.com
Amanda JonesAmanda Jones
Hello Amit,

Thank you so much! We're almost there. When I test the code these lines are not covered:

    else if (Trigger.isDelete)
    {
        for (Opportunity o : trigger.old)
        {
            if ( o.CampaignID != null )
                campIds.add(o.CampaignId);

Any idea what might be wrong?
Amanda JonesAmanda Jones
Yes, I am. Here is my test class:


/* **********************************************************************************
 *
 * Trigger Unit Test: Total Amount Received for Campaign Rollup
 * Created by: Amanda Jones
 *
 * Goal: Testing Trigger - Total Amount Received for Campaign Rollup
 *
 * Coverage: 100%
 *
 *
 *********************************************************************************** */
 
@isTest
 private class TEST_TotalAmountReceived {
 
static testMethod void testTotalAmountReceived() {
 
// Create a test campaign
Campaign c = new Campaign ();
c.Name = 'UnitTest';
insert c;
System.assert(c != null);
 
// Create a test opportunity for the campaign
Opportunity o = new Opportunity ();
o.Name = 'UnitTest';
o.StageName = 'Closed Won';
o.CloseDate = Date.Today();
o.CampaignID = c.ID;
o.Amount = 70.00;
insert o;
System.assert(o != null);
  
// Retrieve the Campaign
Campaign c1 = [SELECT Total_Amount_Received__c FROM Campaign WHERE Id = :c.Id];
System.assertEquals (70.00, c1.Total_Amount_Received__c);
 
}
 }

And no, the trigger is not working. It will add the donations together, but when I delete a donation it is not subtracting the deleted amount. :(
Amit Chaudhary 8Amit Chaudhary 8
Please try below code in trigger :-
trigger TotalAmountReceivedforCampaign on Opportunity (after insert, after update , After delete ) 
{
 
  // gather campaigns from Opps being updated
  List<String> campIds = new List<String>();
  List<String> campIdRemoved = new List<String>();

	if(Trigger.isInsert || Trigger.isUpdate)
	{
		for (Opportunity o : trigger.new)
		{
			if (o.CampaignID != null && (trigger.isInsert || o.Amount != trigger.oldMap.get(o.id).Amount))
				campIds.add(o.CampaignId);
		}
	}
	else if (Trigger.isDelete)
	{
		for (Opportunity o : trigger.old)
		{
			if ( o.CampaignID != null )
				campIds.add(o.CampaignId);
		}
	}	
 
  if (campIds.size() > 0) 
  {
 
	  Map<id, Campaign> campaigns = new Map<id, Campaign>([SELECT id FROM Campaign WHERE id =: campIds]);
	 
	  // initialize Campaign.Total_Amount_Received__c to zero on all campaigns
	  for (Campaign c : campaigns.values())
	   c.Total_Amount_Received__c= 0;
	 
	  // add all Opp.Amount_Received__c to campaigns
		for (Opportunity o : [SELECT id, Amount, CampaignId FROM Opportunity WHERE CampaignId =: campIds])
		{
			Campaign c = campaigns.get(o.CampaignId);
			c.Total_Amount_Received__c += o.Amount;
		}
 
	// update campaigns
	update campaigns.values();
  }
  
}

And try below Test class:-
@isTest
 private class TEST_TotalAmountReceived {
 
static testMethod void testTotalAmountReceived() 
{
 
	// Create a test campaign
	Campaign c = new Campaign ();
	c.Name = 'UnitTest';
	insert c;
	System.assert(c != null);
	 
	// Create a test opportunity for the campaign
	Opportunity o = new Opportunity ();
	o.Name = 'UnitTest';
	o.StageName = 'Closed Won';
	o.CloseDate = Date.Today();
	o.CampaignID = c.ID;
	o.Amount = 70.00;
	insert o;
	System.assert(o != null);
	  
	// Retrieve the Campaign
	Campaign c1 = [SELECT Total_Amount_Received__c FROM Campaign WHERE Id = :c.Id];
	System.assertEquals (70.00, c1.Total_Amount_Received__c);

	Delete o;
}
}

Please let us know if this will help you


 
This was selected as the best answer
Amanda JonesAmanda Jones
Amit you are a genius! It works perfectly now. Thank you!