+ Start a Discussion
Amanda JonesAmanda Jones 

Confused by system dml exception error

I am stumped.

I have written a trigger that should complete a rollup summary on two currency fields on my Campaigns object. When I run the test class it passes and I get 100% code coverage. But when I validate in my production org I get the following error:

System.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, RollupTotalAmountsandCCFees: execution of AfterInsert caused by: System.NullPointerException: Argument cannot be null. Trigger.RollupTotalAmountsandCCFees: line 57, column 1: []
Stack Trace: Class.TEST_TotalAmountReceived.testTotalAmountReceived: line 32, column 1

Here is my trigger:
/* **********************************************************************************
 *
 * Trigger: Rollup Total Amounts and CC Fees
 * Created by:Amanda Jones
 *
 * Purpose/Methods:
 * - This trigger rolls up all of the Donations (Opportunities) and credit card fees into two
 * - currency fields on a Campaign. It is executed after an insert, update or delete of an
 * - opportunity
 *
 * Unit Test:
 * - TEST_RollupTotalAmountsandCCFees Apex Class
 *
 ************************************************************************************** */
 
trigger RollupTotalAmountsandCCFees 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 and CreditCardFee__c to zero on all campaigns
      for (Campaign c : campaigns.values())
       c.Total_Amount_Received__c= 0;
      for (Campaign c : campaigns.values())
       c.CreditCardFee__c= 0;
      
      // add all Opp.Total_Amount_Received__c and CreditCardFee__c to campaigns
        for (Opportunity o : [SELECT id, Amount, CorrectCC_Fee__c, CampaignId FROM Opportunity WHERE CampaignId =: campIds])

        {
            Campaign c = campaigns.get(o.CampaignId);
            c.Total_Amount_Received__c += o.Amount;
            c.CreditCardFee__c += o.CorrectCC_Fee__c;
        }
  
    // update campaigns
    update campaigns.values();
  }
   
}

And here is the test class:
/* **********************************************************************************
 *
 * Trigger Unit Test: Rollup Total Amounts and CC Fees
 * Created by: Amanda Jones
 *
 * Goal: Testing Trigger - RollupTotalAmountsandCCFees for Campaign Rollup
 *
 * Coverage: 100%
 *
 *
 *********************************************************************************** */
 
@isTest
 private class TEST_RollupTotalAmountsandCCFees {
  
static testMethod void testRollupTotalAmountsandCCFees()
{
  
    // 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.Payment_Method__c = 'card payment';
    o.Amount = 100.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 (100.00, c1.Total_Amount_Received__c );
    Campaign c2 = [SELECT CreditCardFee__c FROM Campaign WHERE Id = :c.Id];
    System.assertEquals (3.00, c2.CreditCardFee__c );
    
    
    Delete o;
    

}
}

Ideas would be most appreciated.

Thank you!
Best Answer chosen by Amanda Jones
Amit Chaudhary 8Amit Chaudhary 8
Please modify your Trigger like below code:-
trigger RollupTotalAmountsandCCFees 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 and CreditCardFee__c to zero on all campaigns
      for (Campaign c : campaigns.values())
       c.Total_Amount_Received__c= 0;
      for (Campaign c : campaigns.values())
       c.CreditCardFee__c= 0;
      
      // add all Opp.Total_Amount_Received__c and CreditCardFee__c to campaigns
        for (Opportunity o : [SELECT id, Amount, CorrectCC_Fee__c, CampaignId FROM Opportunity WHERE CampaignId =: campIds])
        {
            if(campaigns.containsKey(o.CampaignId))
            {
                Campaign c = campaigns.get(o.CampaignId);
                if(o.Amount != null)
                {
                    c.Total_Amount_Received__c += o.Amount;
                }
                if(o.CorrectCC_Fee__c != null)
                {
                    c.CreditCardFee__c += o.CorrectCC_Fee__c;
                }    
            }    
        }
        if(campaigns.size() > 0 )
        {
            update campaigns.values();
        }    
  }
   
}
Please try below test class:-
 
@isTest
private class TEST_RollupTotalAmountsandCCFees 
{
	static testMethod void testRollupTotalAmountsandCCFees()
	{
		// 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.CorrectCC_Fee__c =112;
		o.Payment_Method__c = 'card payment';
		o.Amount = 100.00;
		insert o;
		System.assert(o != null);
		
		Delete o;
	}
}


Please let us know if this will help you
 

All Answers

Amit Chaudhary 8Amit Chaudhary 8
Please modify your Trigger like below code:-
trigger RollupTotalAmountsandCCFees 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 and CreditCardFee__c to zero on all campaigns
      for (Campaign c : campaigns.values())
       c.Total_Amount_Received__c= 0;
      for (Campaign c : campaigns.values())
       c.CreditCardFee__c= 0;
      
      // add all Opp.Total_Amount_Received__c and CreditCardFee__c to campaigns
        for (Opportunity o : [SELECT id, Amount, CorrectCC_Fee__c, CampaignId FROM Opportunity WHERE CampaignId =: campIds])
        {
            if(campaigns.containsKey(o.CampaignId))
            {
                Campaign c = campaigns.get(o.CampaignId);
                if(o.Amount != null)
                {
                    c.Total_Amount_Received__c += o.Amount;
                }
                if(o.CorrectCC_Fee__c != null)
                {
                    c.CreditCardFee__c += o.CorrectCC_Fee__c;
                }    
            }    
        }
        if(campaigns.size() > 0 )
        {
            update campaigns.values();
        }    
  }
   
}
Please try below test class:-
 
@isTest
private class TEST_RollupTotalAmountsandCCFees 
{
	static testMethod void testRollupTotalAmountsandCCFees()
	{
		// 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.CorrectCC_Fee__c =112;
		o.Payment_Method__c = 'card payment';
		o.Amount = 100.00;
		insert o;
		System.assert(o != null);
		
		Delete o;
	}
}


Please let us know if this will help you
 
This was selected as the best answer
Amanda JonesAmanda Jones
Hello Amit,

There was a compile error: Field is not writeable - which was caused by this line in the test class "o.CorrectCC_Fee__c =112;", but I deleted it and then everything worked perfectly.

Thank you!