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
nil_von_9wonil_von_9wo 

How do I trigger Account.AnnualRevenue to update when Product is updated?

In my developer environment, I've added two custom fields to the Product standard object:

 

Account: Lookup (Account)

Annual Revenue: Formula (Currency) 

 

The formula for Product2.Annual_Revenue is:

 

 Annual_Revenue = Estimated_Monthly_Sales_Volume__c * Total_CO2_Footprint__c *0.0024

 

 

 

I'm trying to create a trigger so that when a Product is added or modified, the AnnualRevenue field in Accounts will automatically reflect the total value of all Products which lookup that account.

 

This is the trigger I've created:

 

trigger UpdateAccountAnnualRevenue 

on Product2 (after delete, after insert, after undelete, after update) 

{

for (Product2 productModified: Trigger.new)

{

List <Product2> accountProduct =

[

select Annual_Revenue__c

from Product2

where ID = :productModified.Account__r.id

];

double Total_Revenue = 0.00;

for (Product2 AP: accountProduct)

{

Total_Revenue += AP.Annual_Revenue__c;

}

for (Account productAccount: 

[

select AnnualRevenue

from Account

where ID = :productModified.Account__r.id

)

{

productAccount.AnnualRevenue = Total_Revenue;

update productAccount;

}

}

 

}

 

 

However, there seems to be a problem with this code.

 

For example, GenWatt Diesel 200kW has an Annual Revenue of $18.67.

 

However, the account Burlington Textiles Corp of America, which has no other assigned products, has an Annual Revenue of $350,000,000

 

 

 

What am I doing wrong and how do I fix it?  

Message Edited by nil_von_9wo on 07-09-2009 07:04 AM
Best Answer chosen by Admin (Salesforce Developers) 
nil_von_9wonil_von_9wo

Cheers for the solution above!

 

I think you're looking for "Account__c"?

 

I noticed when I tried to get the code to work, I needed to add a semi-colon to line 9, as well as add "Account_c" to line 13.

 

But other than that, the code works great and it would have taken me a long time to figure this out without you!  :-)

 

 

 Corrected code, in case anyone else is interested:

 

trigger UpdateAccountAnnualRevenue 

on Product2 (after delete, after insert, after undelete, after update) 

{

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

 

for (Product2 productModified: Trigger.new)

{

    if(productModified.Account__c  == null) return;

    accIds.add(productModified.Account__c);

}

 

List<Product2> prodList = new List<Product2>([

Select Id, Account__c, Annual_Revenue__c

from Product2

where Account__c In : accIds]);

 

Map<Id, double> accountTotalRevenueMap = new Map<Id, double>();

 

for (Product2 productModified: Trigger.new)

{

    if(productModified.Account__c  == null) return;

 

    if(!prodList.isEmpty())

    {

          double Total_Revenue = 0.00;

 

          for(Product2 oldProd : prodList)

          {

                if(oldProd.Account__c == productModified.Account__c

                    &&  oldProd != productModified)

                {

                       Total_Revenue += oldProd.Annual_Revenue__c;

                }

          } 

 

          accountTotalRevenueMap.put(productModified.Account__c, Total_Revenue);

    }

}

 

for(List<Account> accList : [Select Id, AnnualRevenue From Account Where Id In : accIds] )

{

      for(Account a : accList)

      {

             if(accountTotalRevenueMap.get(a.Id) == null)return;

             a.AnnualRevenue = accountTotalRevenueMap.get(a.Id);

      }

 

      update accList;

}


} 

 

Message Edited by nil_von_9wo on 07-09-2009 07:59 AM

All Answers

Guyver118Guyver118

try this

 

 

 

List <Product2> accountProduct =

[

select Annual_Revenue__c

from Product2

where ID = productModified.Account__c

];

 

 

but i see loads of problems with ur trigger it is not bulk safe.

nil_von_9wonil_von_9wo
Thanks for the response... trying presently.

If it's not too much trouble, I don't suppose you can provide a complete code that will make this work correctly?

I'm quite new at SalesForce.com and Apex...

Thanks in advance,

-Brian.
nil_von_9wonil_von_9wo
Didn't work... now the value for Account.AnnualRevenue is equal to $0, no matter what values are in the corresponding Product(s).

[Note: I haven't tested Accounts with multiple products yet since I don't expect it to work with 2 Products when it doesn't work for accounts with 1.]
Guyver118Guyver118
Basically do u want to update the account that is attached to the product2 table hold on let me try something for u?
nil_von_9wonil_von_9wo

Right.

 

Each Product is attached to an Account by a lookup field.

 

The standard Account object already has "AnnualRevenue" as a Currency (18,0) field.

 

My client wishes for the value of this field to be the total value of all Products which lookup this account.

 

Because I can't (for reasons that are beyond me) add Account as a Master in a Master-Detail relationship to Product, it isn't possible for me to simply create this sum as a Rollup field in Account.

 

So, for lack of any better idea how to do this, I thought I'd try to do this with a trigger. (I am, however, open to alternative suggestions.)

 

 

-Brian. 

 

 

Guyver118Guyver118
 am nearly done hold one a few mins
Guyver118Guyver118

try this:

 

 

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

 

for (Product2 productModified: Trigger.new)

{

     if(productModified.Account__c  == null) return;

     accIds.add(productModified.Account__c)

}

 

List<Product2> prodList = new List<Product2>([

Select Id, Annual_Revenue__c

from Product2

where Account__c In : accIds]);

 

Map<Id, double> accountTotalRevenueMap = new Map<Id, double>();

 

for (Product2 productModified: Trigger.new)

{

     if(productModified.Account__c  == null) return;

 

     if(!prodList.isEmpty())

     {

           double Total_Revenue = 0.00;

 

           for(Product2 oldProd : prodList)

           {

                 if(oldProd.Account__c == productModified.Account__c

                     &&  oldProd != productModified)

                 {

                        Total_Revenue += oldProd.Annual_Revenue__c;

                 }

           } 

 

           accountTotalRevenueMap.put(productModified.Account__c, Total_Revenue);

     }

}

 

for(List<Account> accList : [Select Id, AnnualRevenue From Account Where Id In : accIds] )

{

       for(Account a : accList)

       {

              if(accountTotalRevenueMap.get(a.Id) == null)return;

              a.AnnualRevenue = accountTotalRevenueMap.get(a.Id);

       }

 

       update accList;

}

 

 

Guyver118Guyver118
what is the api name for the account on the product2 table
Guyver118Guyver118
buzz if it works probably needs a few tweaks but it should work :0
nil_von_9wonil_von_9wo

Cheers for the solution above!

 

I think you're looking for "Account__c"?

 

I noticed when I tried to get the code to work, I needed to add a semi-colon to line 9, as well as add "Account_c" to line 13.

 

But other than that, the code works great and it would have taken me a long time to figure this out without you!  :-)

 

 

 Corrected code, in case anyone else is interested:

 

trigger UpdateAccountAnnualRevenue 

on Product2 (after delete, after insert, after undelete, after update) 

{

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

 

for (Product2 productModified: Trigger.new)

{

    if(productModified.Account__c  == null) return;

    accIds.add(productModified.Account__c);

}

 

List<Product2> prodList = new List<Product2>([

Select Id, Account__c, Annual_Revenue__c

from Product2

where Account__c In : accIds]);

 

Map<Id, double> accountTotalRevenueMap = new Map<Id, double>();

 

for (Product2 productModified: Trigger.new)

{

    if(productModified.Account__c  == null) return;

 

    if(!prodList.isEmpty())

    {

          double Total_Revenue = 0.00;

 

          for(Product2 oldProd : prodList)

          {

                if(oldProd.Account__c == productModified.Account__c

                    &&  oldProd != productModified)

                {

                       Total_Revenue += oldProd.Annual_Revenue__c;

                }

          } 

 

          accountTotalRevenueMap.put(productModified.Account__c, Total_Revenue);

    }

}

 

for(List<Account> accList : [Select Id, AnnualRevenue From Account Where Id In : accIds] )

{

      for(Account a : accList)

      {

             if(accountTotalRevenueMap.get(a.Id) == null)return;

             a.AnnualRevenue = accountTotalRevenueMap.get(a.Id);

      }

 

      update accList;

}


} 

 

Message Edited by nil_von_9wo on 07-09-2009 07:59 AM
This was selected as the best answer
Guyver118Guyver118

On another note u should probably build a class out of that trigger and get the trigger to call the class function

as for after delete you probably have to get the trigger.old

 

public class Product2Utils {

static void CheckAnnualRevenue(List<Product2> prodList)

{

    //put code here

}

 

}

Guyver118Guyver118

or try this :

 

 

trigger UpdateAccountAnnualRevenue on Product2 (after delete, after insert, after undelete, after update) { List<Product2> triggerList = (trigger.isDelete || trigger.isUndelete ? trigger.old : trigger.new); Set<Id> accIds = new Set<Id>(); for(Product2 productModified: triggerList) { if(productModified.Account__c == null) return; accIds.add(productModified.Account__c); } List<Product2> prodList = new List<Product2>([ Select Id, Account__c, Annual_Revenue__c from Product2 where Account__c In : accIds]); Map<Id, double> accountTotalRevenueMap = new Map<Id, double>(); for(Product2 productModified: triggerList) { if(productModified.Account__c == null || prodList.isEmpty())return; Double total_Revenue = 0.00; for(Product2 oldProd : prodList) { if(oldProd.Account__c == productModified.Account__c && oldProd != productModified) { total_Revenue += oldProd.Annual_Revenue__c; } } accountTotalRevenueMap.put(productModified.Account__c, total_Revenue); } if(!accountTotalRevenueMap.isEmpty()) { for(List<Account> accList : [Select Id, AnnualRevenue From Account Where Id In : accIds] ) { for(Account a : accList) { if(accountTotalRevenueMap.get(a.Id) == null)return; a.AnnualRevenue = accountTotalRevenueMap.get(a.Id); } update accList; } } }

 

 

 

nil_von_9wonil_von_9wo
Cheers for the revision... I would have completely missed the isDelete and isUndelete possibilities!

-Brian.