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
Pawan RaiPawan Rai 

How to create rollup using Apex trigger

Hi,

 

I want to create a rollup field in Account Object with Opportunity Amount. Can any one help me on this, Actually i'm new in  trigger.

Best Answer chosen by Admin (Salesforce Developers) 
sfdcfoxsfdcfox

sales4ce:

 

Your trigger code is overly complex, uses too many database queries, and has an unoptimized database query. All of your code can be summarized quite elegantly as:

 

trigger contactRollup on Testing__c (after insert, after update, after delete, after undelete) {
  Map<Id,Contact> updateContacts = new Map<Id,Contact>();
  Set<Id> updateContactIds = new Map<Id,Contact>();
  // If we are inserting, updating, or undeleting, use the new ID values
  if(Trigger.isInsert || Trigger.isUpdate || Trigger.isUndelete)
    for(Testing__c testing:Trigger.new)
      updateContactIds.add(testing.Contact_Name__c);
  // If we are updating, some contacts might change, so include that as well as deletes
  if(Trigger.isUpdate || Trigger.isDelete)
    for(Testing__c testing:Trigger.old)
      updateContactIds.add(testing.Contact_Name__c);
  // Do not create a record for null field
  updateContactIds.remove(null);
  // Create in-memory copies for all contacts that will be affected
  for(Id contactId:updateContactIds)
    updateContacts.put(contactId,new Contact(id=contactId,Testings_Count__c=0);
  // Run an optimized query that looks for all contacts that meet the if/then criteria
  for(Testing__c testing:[select id,contact_name__c from testing where contact_name__c in :updateContactIds and Decision__c='Good'])
    updateContacts.get(testing.contact_name__c).Testings_Count__c++;
  // Update all the contacts with new values.
  Database.update(updateContacts.values());
}

As you can see, I gather all contact ID values that will be involved with recalculation, including the scenario where the field changes from, for example, "Bob Smith" to "Jane Doe". I then create in-memory references to these records so I can update them. Finally, I run a query to find all Testing__c records for all contacts that meet the additional criteria of Decision__c = 'Good'. Finally, we update the database with the new values.

 

 

 

All Answers

sfdcfoxsfdcfox

Usually, that can be accomplished using the generic following type of trigger:

 

 

trigger doRollup on Child__c (after insert, after update, after delete, after undelete) {
  // List of parent record ids to update
  Set<Id> parentIds = new Set<Id>();
  // In-memory copy of parent records
  Map<Id,Parent__c> parentRecords = new Map<Id,Parent__c>();
  // Gather the list of ID values to query on
  for(Child__c c:Trigger.isDelete?Trigger.old:Trigger.new)
    parentIds.add(c.ParentField__c);
  // Avoid null ID values
  parentIds.remove(null);
  // Create in-memory copy of parents
  for(Id parentId:parentIds)
    parentRecords.put(parentId,new Parent__c(Id=parentId,RollupField__c=0));
  // Query all children for all parents, update Rollup Field value
  for(Child__c c:[select id,Amount__c,ParentField__c from Child__c where id in :parentIds])
    parentRecords.get(c.ParentField__c).RollupField__c += c.Amount__c;
  // Commit changes to the database
  Database.update(parentRecords.values());
}

 

For more information on the steps I have used here, you might read on Set and Map collections, as well as for-SOQL loops.

 

skodisanaskodisana

Hi,

 

Salesforce out of the Box will allow Roll up summary field on Account object with  Summarized Object as Opportunity.

with this you can display Sum of Amount of the related opportunities for a given Account.

 

Thanks,

Kodisana

test pawantest pawan

Thanks, but I want code for that, how we can write.

 

Thanks,

Pawan

sales4cesales4ce

Hi,

 

I have something similar, but unable to get it to work.

I have to count the number of records and then roll up the statistics up to the parent.Of course, the objects have a look up.So trigger is the only way to go about.

 

Based on child records status__c field i need to roll up, but i cant get it to work for some reason.

i am not quite sure if this is the way to go.

 

Any help is highly appreciated.

 

trigger contactRollup on Testing__c (after Insert, after Update,after Delete,after undelete) {


    set<Id> testId=New set<Id>();
    Set<Id> contactId=new Set<Id>();
    List<Contact> updateCount=New List<Contact>();
    Integer testRec;
    if(Trigger.isInsert){
    
        for(Testing__c test: Trigger.New){
            if(test.Decision__c=='Good'){
                testId.add(test.Id);
                contactId.add(test.Contact_Name__c);
                }
        }
    
        testRec=[Select Count() From Testing__c Where Id IN:testId];
        List<Contact> ct=[select Testings_Count__c from Contact Where Id IN:contactId];
        
        for(Contact c:ct){
            c.Testings_Count__c+=testRec;
            updateCount.add(c);
        }
        
        update updateCount;
    }
    
    else if(Trigger.isUpdate){
        set<Id> decrementId=New Set<Id>();
        set<Id> contactdecId=New Set<Id>();
        
        for(Testing__c te: Trigger.New){
        
            if(te.Decision__c!=Trigger.oldMap.get(te.Id).Decision__c && te.Decision__c=='Good'){
                testId.add(te.Id);
                contactId.add(te.Contact_Name__c);
            }
            
            if(te.Decision__c!=Trigger.oldMap.get(te.Id).Decision__c && te.Decision__c!='Good'){
            
                decrementId.add(te.Id);
                contactdecId.add(te.Contact_Name__c);
            }
        }
        
        Integer testRec1=[Select Count() From Testing__c where Id IN:decrementId];
        List<Contact> changecont=[Select Testings_Count__c from Contact where Id IN: contactdecId];
        testRec=[Select Count() From Testing__c where Id IN:testId];
        List<Contact> c=[Select Testings_Count__c from Contact where Id IN: contactId];
        
        for(Contact cts:c){
            cts.Testings_Count__c+=testRec;
            updateCount.add(cts);
        }
        
        for(Contact conts:changecont){
            conts.Testings_Count__c-=testRec1;
            updateCount.add(conts);
        }
        
        update updateCount;
    }
    
    else if(Trigger.isDelete){
    
        for(Testing__c tes:Trigger.Old){
            if(tes.Decision__c=='Good'){
                testId.add(tes.Id);
                contactId.add(tes.Contact_Name__c);
            }
        }
        testRec=[Select Count() From Testing__c where Id IN:testId];
        List<Contact> con=[Select Testings_Count__c from Contact where Id IN: contactId];
        
        for(Contact conts:con){
            conts.Testings_Count__c-=testRec;
            updateCount.add(conts);
        }
        
        Update updateCount;
    }
    
    else if(Trigger.isUndelete){
        for(Testing__c tes:Trigger.New){
            if(tes.Decision__c=='Good'){
                testId.add(tes.Id);
                contactId.add(tes.Contact_Name__c);
            }
        }
        testRec=[Select Count() From Testing__c where Id IN:testId];
        List<Contact> con=[Select Testings_Count__c from Contact where Id IN: contactId];
        
        for(Contact conts:con){
            conts.Testings_Count__c+=testRec;
            updateCount.add(conts);
        }
        
        Update updateCount;
    }
    
}

 

 

Thanks,

Sales4ce

 

sfdcfoxsfdcfox

sales4ce:

 

Your trigger code is overly complex, uses too many database queries, and has an unoptimized database query. All of your code can be summarized quite elegantly as:

 

trigger contactRollup on Testing__c (after insert, after update, after delete, after undelete) {
  Map<Id,Contact> updateContacts = new Map<Id,Contact>();
  Set<Id> updateContactIds = new Map<Id,Contact>();
  // If we are inserting, updating, or undeleting, use the new ID values
  if(Trigger.isInsert || Trigger.isUpdate || Trigger.isUndelete)
    for(Testing__c testing:Trigger.new)
      updateContactIds.add(testing.Contact_Name__c);
  // If we are updating, some contacts might change, so include that as well as deletes
  if(Trigger.isUpdate || Trigger.isDelete)
    for(Testing__c testing:Trigger.old)
      updateContactIds.add(testing.Contact_Name__c);
  // Do not create a record for null field
  updateContactIds.remove(null);
  // Create in-memory copies for all contacts that will be affected
  for(Id contactId:updateContactIds)
    updateContacts.put(contactId,new Contact(id=contactId,Testings_Count__c=0);
  // Run an optimized query that looks for all contacts that meet the if/then criteria
  for(Testing__c testing:[select id,contact_name__c from testing where contact_name__c in :updateContactIds and Decision__c='Good'])
    updateContacts.get(testing.contact_name__c).Testings_Count__c++;
  // Update all the contacts with new values.
  Database.update(updateContacts.values());
}

As you can see, I gather all contact ID values that will be involved with recalculation, including the scenario where the field changes from, for example, "Bob Smith" to "Jane Doe". I then create in-memory references to these records so I can update them. Finally, I run a query to find all Testing__c records for all contacts that meet the additional criteria of Decision__c = 'Good'. Finally, we update the database with the new values.

 

 

 

This was selected as the best answer
sravusravu

I have a simple trigger that acts as similar to a roll up summary field - count (between  opportunity and account). Try this and see if this meets your requirement.

 

trigger rollupfieldupdate on Opportunity (after insert, after delete) {
    public Id aId;
    
    if(Trigger.isInsert){
        for(Opportunity opp : Trigger.New){
            aId = opp.AccountId;
        }
        List<Account> acc = [select id,roll_up_field__c from Account where Id=:aId];
        for(Account a : acc){
            a.roll_up_field__c=a.roll_Up_field__c+1;
            update a;
        }
    }
    if(Trigger.isDelete){
        for(Opportunity opp : Trigger.old){
            aId = opp.AccountId;
        }
        List<Account> acc = [select id,roll_up_field__c from Account where Id=:aId];
        for(Account a : acc){
            a.roll_up_field__c=a.roll_Up_field__c-1;
            update a;
        }
    }
}

 

Let me know if you face any difficulty..................

Hope this helps you.

sfdcfoxsfdcfox

sravu,

 

Your simple code does indeed work for user interface edits that involve only one opportunity at a time. However, it ignores some possible scenarios that could occur:

 

 

  • If AccountID is empty on creation, the account will not be credited correctly.
  • If AccountID is set to empty after creation, on deletion the account will not be debited correctly.
  • If AccountID is changed at any time, the old account will not be debited, nor the new account credited.
  • If a user uses the Mass Delete wizards, API, etc, your accounts will not be in sync for all but one account per 200 opportunities.
  • If multiple opportunities are created or deleted at the same time on a single account, only one of those will be debited or credited.
While I do applaud your attempt at creating an optimized trigger (because, indeed, the number of query rows are far lower than my example is guaranteed to be), it does not support bulk actions correctly. In fact, if your variables were set up correctly (using a Set instead of a scalar variable), you would then run into a DML governor limit. You should never place DML operations inside a for loop without making sure that you are only operating on a full batch of records or at the end of a loop. This trigger also ignores existing records, which will result in incorrect counts.

 

JensenleeJensenlee

Dear sddcfox,

 

Pardon my coding as I am very new to apex with little knowledge of programming.

I am using your sample to try fit into my requirements but I am wondering if it can be use to reflect text nstead of rollup numerics - in the parent object?

 

I have a custom object: Context__C which is a child of parent object End_Market__C

I am trying to display a text field Operating_Model_Child__c (in Context__C) into Operating_Model_Parent__c text field in (in End_Market__C)

 

The query will only return one record as there is only one Active record (under Status__C) per in Context per End Market at any one time.

 

The objective is simply to disply a field in a that is active in the child records.

Am using APEX this as there seem to be no other altnenatives for displaying text using the standard functions :(

 

 

trigger doRollup on Context__c (after insert, after update, after delete, after undelete) {
 
  // List of parent record ids to update
  Set<Id> parentIds = new Set<Id>();
 
  // In-memory copy of parent records
  Map<Id,End_Markets__c> parentRecords = new Map<Id,End_Markets__c>();
 
  // Gather the list of ID values to query on
  for(Context__c c:Trigger.isDelete?Trigger.old:Trigger.new)
    parentIds.add(c.Operating_Model_Parent__c);
 
  // Avoid null ID values
  parentIds.remove(null);
 
  // Create in-memory copy of parents
  for(Id parentId:parentIds)
    parentRecords.put(parentId,new End_Markets__c(Id=parentId,Operating_Model_Child__c=0));
 
  // Query all children for all parents, update Rollup Field value
  for(Context__c c:[select id,Operating_Model_Parent__c from Context__c where id in :parentIds and Status__c = 'Active'])
    parentRecords.get(c.Operating_Model_Parent__c).Operating_Model_Child__c;
 
  // Commit changes to the database
  Database.update(parentRecords.values());
}

sfdcfoxsfdcfox

I assume you mean to say that Operating_Model_Child__c is a lookup, not a text field? You've got it almost right, with just a couple small bugs here:

 

 

parentRecords.put(parentId,new End_Markets__c(Id=parentId,Operating_Model_Child__c=null));

 

parentRecords.get(c.Operating_Model_Parent__c).Operating_Model_Child__c = c.Id;

Since Lookup fields are text, use NULL, not zero ("0") to assign a null value. Secondly, your last loop should have been an assignment, and it was not assigning a new value.

 

 

I'm just basing my assumptions off your code, but hopefully this will point you in the right direction.

 

JensenleeJensenlee

Dear sfdcfox,

 

Really appreciate your reply.

I tried to understand the logic of your codes but I am really struggling! I get abit confused with the definition of ParentField__c

Context__c has a lookup field named End_Markets_Child__c linked to the parent object - End_Market__c

So Operating Model_Child__c field in Context__c and Operating Model_Parent__c in End_Market__c are both text fields

 

I made the changes to the code as you has indicated but an error appeared as the following

Error: Compile Error: Invalid field Operating_Model_Child__c for SObject End_Markets__c at line 18 column 88 

 

trigger doRollup on Context__c (after insert, after update, after delete, after undelete) {
 
  // List of parent record ids to update
  Set<Id> parentIds = new Set<Id>();
 
  // In-memory copy of parent records
  Map<Id,End_Markets__c> parentRecords = new Map<Id,End_Markets__c>();
 
  // Gather the list of ID values to query on
  for(Context__c c:Trigger.isDelete?Trigger.old:Trigger.new)
  parentIds.add(c.Operating_Model_Parent__c);
 
  // Avoid null ID values
  parentIds.remove(null);
 
  // Create in-memory copy of parents
  for(Id parentId:parentIds)
  parentRecords.put(parentId,new End_Markets__c(Id=parentId,Operating_Model_Child__c=null));
 
  // Query all children for all parents, update Rollup Field value
  for(Context__c c:[select id,Operating_Model_Parent__c from Context__c where id in :parentIds and Status__c =True])
  parentRecords.get(c.Operating_Model_Parent__c).Operating_Model_Child__c = c.Id;
 
  // Commit changes to the database
  Database.update(parentRecords.values());
}

sfdcfoxsfdcfox

I apologize for the late reply, but here goes:

 

End_Markets__c is one object, Context__c is the other. On Context__c, there is a field called Operating_Model_Parent__c, and on the End_Markets__c object, is a field Operating_Model_Child__c. These are not your field names, but since you never provided me with a field name for these, I just made something up. You need to modify the code to suit your environment.

theekid02theekid02

Thank you for the code post Fox, really appreciate it! I am working for a non-profit and have added a field name Number of hours on the campaign members object and a total hours field on the contacts object. This is to allow me to rollup the total number of "Confirmed" hours a contact has working on campaigns. I cant figure out what I am doing wrong after altering your code, any help would be a godsend.

 

trigger contactRollup on campaignmember (after insert, after update, after delete, after undelete) {

  Map<Id,Contact> updateContacts = new Map<Id,Contact>();

 

  Set<Id> updateContactIds = new Map<Id,Contact>();

 

  // If we are inserting, updating, or undeleting, use the new ID values

  if(Trigger.isInsert || Trigger.isUpdate || Trigger.isUndelete)

    for(campaignmember campaignmember:Trigger.new)

      updateContactIds.add(campaignmember.Contact_Name__c);

 

  // If we are updating, some contacts might change, so include that as well as deletes

  if(Trigger.isUpdate || Trigger.isDelete)

    for(campaignmember campaignmember:Trigger.old)

      updateContactIds.add(campaignmember.Contact_Name__c);

 

 

  // Do not create a record for null field

  updateContactIds.remove(null);

 

 

  // Create in-memory copies for all contacts that will be affected

  for(Id contactId:updateContactIds)

    updateContacts.put(contactId,new Contact(id=contactId, Total_Hours__c=0));

 

 

  // Run an optimized query that looks for all contacts that meet the if/then criteria

  for(campaignmember campaignmember:[select id, numer_of_hours from campaignmember where id in :updateContactIds and Status__c='Confirmed'])

    updateContacts.get(campaignmember.contact_name__c).Total_Hours__c += campaignmembers.Number_of_Hours;

 

 

  // Update all the contacts with new values.

  Database.update(updateContacts.values());

}

GespitzGespitz

~ sfdcfox ~

 

I am using your generic trigger to roll-up opportunity amount in my contacts, but is not addin the amount. If I change the 0 for any other number, the roll-up changes, so is running and is getting to that part of the logic, buf if not I just get a 0 on the field. Any tip??

 

Thanks!

 

Gespitz

GespitzGespitz

It's owrking, I just need to add a condition that compares the opportunitty closeddate to see if it is in current year. I am trying a lot of ways but I cannot write that comparision.

 

Thanks!!

 

German

rajesh4sfdcrajesh4sfdc

.

As you mentioned above trigger in the for loop

 

for(Account a : acc){
a.roll_up_field__c=a.roll_Up_field__c + 1;
update a;

 

 

ErrorError: Compile Error: Field is not writeable: Account.roll_up_field__c at line 10 column 13
rjenkinsDWMrjenkinsDWM

sdfcfox,

 

 

DId you create a test class for this? It seems to be just what I need but I need the unit test class.

 

Thanks for your consideration.

RJ

highland23highland23

sfdcfox:

 

I really like what you have with the selected solution in this thread; however, we're running into a situation where we're using this to do counts that are greater than 50,000 records.  We've read about the ability to use @ReadOnly annotation, which seems like a good fit since all we need to do is get the count and then drop its value in the parent object.  The challenges seems to be that this can't be done in a trigger, correct?  Might you have a recommendation as to how this could be built into a class instead, referenced by the trigger, so we can use the @ReadOnly annotation?

 

Thanks!

S91084S91084
Hi, You can write the function in an apex class and call the class method in trigger.
fourfourfunfourfourfun

Hi Mr Fox,

 

I'm trying to figure out how to do a rollup where the relationship is a lookup field. My biggest bugbear is where to start customising the generic code.

 

Am I literally diving in and replacing parent/child with my custom objects, and then references to what to sum and where to sum it?

 

 

GregDevGregDev

Hi

Am a novice - But thought I would try and use your code as a pattern.

 

Have a  related list under Accounts for Buddy  Connections - Objec t is  "Buddy_Connection__c"

Have a number field on account   BD_Connections_Current__c which i want poulated with count of "Buddy Connections" where Status_of_Buddy_Day__c='Current'

 

Get this message

 

Line 19 sObject type 'Buddy_Connection' is not supported....

 

Code is

 

 

trigger OrgCountCurrentBuddyConnections on Buddy_Connection__c (after insert, after update, after delete, after undelete)
{
Map<Id,Account> updateAccounts = new Map<Id,Account>();
Set<Id> updateAccountIds = new Map<Id,Account>();
// If we are inserting, updating, or undeleting, use the new ID values
if(Trigger.isInsert || Trigger.isUpdate || Trigger.isUndelete)
for(Buddy_Connection__c Buddy_Connection:Trigger.new)
updateAccountIds.add(Buddy_Connection.Account_Name__c);
// If we are updating, some contacts might change, so include that as well as deletes
if(Trigger.isUpdate || Trigger.isDelete)
for(Buddy_Connection__c Buddy_Connection:Trigger.old)
updateAccountIds.add(Buddy_Connection.Account_Name__c);
// Do not create a record for null field
updateAccountIds.remove(null);
// Create in-memory copies for all Accounts that will be affected
for(Id AccountId:updateAccountIds)
updateAccounts.put(AccountId,new Account(id=AccountId,BD_Connections_Current__c=0));
// Run an optimized query that looks for all Accounts that meet the if/then criteria
for(Buddy_Connection__c Buddy_Connection:[select id,Account_name__c from Buddy_Connection where Account_Name__c in :updateAccountIds and Status_of_Buddy_Day__c='Current'])
updateAccount.get(Buddy_Connection.Account_name__c).BD_Connections_Current__c++;
// Update all the Accounts with new values.
Database.update(updateAccount.values());
}

 

rjenkinsDWMrjenkinsDWM
I think the FROM object (Buddy_Connection) needs the __c appended in your
select statement.

*

Ron Jenkins*
*Consultant*

Mobile: +1-719-352-8504

Skype: rjenkins5725

MicroPlanet Technologies

www.microplanettech.org
fourfourfunfourfourfun

I've hit a rollup limit on a custom object, going to sit down with this to see if it can provide a solution.

fourfourfunfourfourfun

Ok, I have got as far as this, when I get a Loop variable must be of type SOBJECT:Time_Record__c at line 10 column 28.

 

trigger doRollup on Time_Record__c (after insert, after update, after delete, after undelete) {

  // List of parent record ids to update
    Set<Id> parentIds = new Set<Id>();
  
  // In-memory copy of parent records
  Map<Id,Time_Record__c> parentRecords = new Map<Id,Time_Record__c>();
  
  // Gather the list of ID values to query on
  for(Daily_Time_Record__c c:Trigger.isDelete?Trigger.old:Trigger.new)
    parentIds.add(c.Time_Record_Link__c);
    
  // Avoid null ID values
  parentIds.remove(null);
  
  // Create in-memory copy of parents
  for(Id parentId:parentIds)
    parentRecords.put(parentId,new Time_Record__c(Id=parentId,RollupTarget__c=0));
    
  // Query all children for all parents, update Rollup Field value
  for(Daily_Time_Record__c c:[select id,FieldToRoll__c,Time_Record_Link__c from Daily_Time_Record__c where id in :parentIds])
    parentRecords.get(c.Time_Record_Link__c).RollupTarget__c += c.FieldToRoll__c;
    
  // Commit changes to the database
  
  Database.update(parentRecords.values());
}

 

so obviously need to get myself past that point.

sfdcfoxsfdcfox
Line 10 should be:

for(Time_Record__c c:Trigger.isDelete?Trigger.old:Trigger.new)
fourfourfunfourfourfun

Ah: Trigger should have been on Child not on Parent. It now saves, but doesn't actually do anything.

 

Also just noted the above, changing the trigger to the child fixed it so it saved. Now to troubleshoot why it isn't doing anything. I can only imagine the SoQL at the end isn't doing anything... but I have no idea how to debug that to prove it.

 

EDIT:

 

Yep.

 

where id in :parentIds]

 

should have been

 

where Time_Record_Link__c in :parentIds]

 

Some testing to do but that should be it.

 

EDIT 2:

 

Can I make it do a MAX instead of SUM?

sfdcfoxsfdcfox
parentRecords.get(c.Time_Record_Link__c).RollupTarget__c += c.FieldToRoll__c;

// Change to:

parentRecords.get(c.Time_Record_Link__c).RollupTarget__c = Math.max(parents.get(c.Time_Record_Link__c).RollupTarget__c, c.FieldToRoll__c);

Or you could change the loop to an aggregate query:

 

for(AggregateResult ar:[SELECT Time_Record_Link Id, MAX(FieldToRoll__c) maxValue FROM Daily_Time_Record__c WHERE Time_Record_Link__c IN :parentIds GROUP BY Time_Record_Link__c]) {
  parentRecords.get((id)ar.get('Id')).RollupTarget__c = (Decimal)ar.get('maxValue');
}

 

Property ITProperty IT
Hi Brian, Just curious, I am an apex newbie and would like to clarify, Lookup Account Child Sale_Joint_Name__c Correct me if i am wrong for the items below with reference to your code Field in Account is Total_Joint_Sales_Value = ParentField__c Total calculated field in Sale_Joint_Name__c is Sales_Value__c = Amount__c where is Rollupfield__c?
Property ITProperty IT
Im a bit confused to what ParentField__c is refering to? Some light please. newbie here.
Property ITProperty IT

Hey there. Im sorry for the earlier confusion but i tried using the same code with changes but it doesn't work. It runs without errors but I am still getting 0 values.

 

The Object I am doing the trigger is on Sales Joint Name (SaleJointName__c) to update a field in Account:

  1. Master Detail Relationship with Account - Joint_Buyer__c
  2. Lookup Relationship with Opportunity - Opportunity__c

 

Field in Account to update (sum) : Total_Sales_Joint_Value__c (Currency)

Field in Sales Joint Name to rollup : Sales_Value__c (Currency)

 

 

trigger sumRollup on SaleJointName__c (after insert, after update, after delete, after undelete) {

   

  // List of parent record ids to update

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

   

  // In-memory copy of parent records

  Map<Id,Account> parentRecords = new Map<Id,Account>();

 

  // Gather the list of ID values to query on

  for(SaleJointName__c c:Trigger.isDelete?Trigger.old:Trigger.new)

    parentIds.add(c.Joint_Buyer__c );

 

  // Avoid null ID values

  parentIds.remove(null);

 

 // Create in-memory copy of parents

  for(Id parentId:parentIds)

    parentRecords.put(parentId,new Account(Id=parentId,Total_Sales_Joint_Value__c=0));

 

  // Query all children for all parents, update Rollup Field value

  for(SaleJointName__c c:[select id,Sales_Value__c,Joint_Buyer__c from SaleJointName__c where id in :parentIds])

    parentRecords.get(c.Joint_Buyer__c).Total_Sales_Joint_Value__c+= c.Sales_Value__c;

 

  // Commit changes to the database

  Database.update(parentRecords.values());

}

Admin User 586Admin User 586
Hi sfdcfox,

I am trying to implement your apex code to create a rollup summary from campaigns to contacts and would really appreciate some help. Contacts are associated with campaigns through a lookup field called Chosen_Tutor__c.

What I am trying to do is to create a rollup summary of a number field called Hours_per_week__c on the object campaigns into a number field on the related contact called Live_Hours_Rollup__c. The condition of the rollup should be that only campaigns with status "Live job" are summarised. I have pasted the code that I have tried to implement below which is not working:
 
trigger Livehoursrollup on campaign (after insert, after update, after delete, after undelete) {
  Map<Id,Contact> updateContacts = new Map<Id,Contact>();
  Set<Id> updateContactIds = new Map<Id,Contact>();
  // If we are inserting, updating, or undeleting, use the new ID values
  if(Trigger.isInsert || Trigger.isUpdate || Trigger.isUndelete)
    for(campaign campaign:Trigger.new)
      updateContactIds.add(campaign.Chosen_Tutor__c);
  // If we are updating, some contacts might change, so include that as well as deletes
  if(Trigger.isUpdate || Trigger.isDelete)
    for(campaign campaign:Trigger.old)
      updateContactIds.add(campaign.Chosen_Tutor__c);
  // Do not create a record for null field
  updateContactIds.remove(null);
  // Create in-memory copies for all contacts that will be affected
  for(Id contactId:updateContactIds)
    updateContacts.put(contactId,new Contact(id=contactId,Live_Hours_Rollup__c=0));
  // Run an optimized query that looks for all contacts that meet the if/then criteria
  for(campaign campaign:[select id,Hours_per_week__c from campaign where Chosen_Tutor__c in :updateContactIds and Status__c='Live job'])
    updateContacts.get(campaign.Chosen_Tutor__c).Live_Hours_Rollup__c++;
  // Update all the contacts with new values.
  Database.update(updateContacts.values());
}

Any chance that you can let me know where I am going wrong?

Thanks!
dharmik thummardharmik thummar
trigger newLeadTrigger on Opportunity (after insert , after update, after delete , after undelete) {
    
    if(trigger.isAfter && (trigger.isInsert || trigger.isUpdate || trigger.isUndelete)){
   		OpportunityCustomRollup.CountRollup(Trigger.new);
    }
    
    if(Trigger.isDelete)
    {
        OpportunityCustomRollup.CountRollup(Trigger.old);
    }
}


Controller Class:
 

public class OpportunityCustomRollup {
   
	public static void CountRollup(List<Opportunity> lstOpportunity){
        
		set<id> oppIds = new set<id>();
        map<string, integer> classroomIDToDeskCountMap = new map<string, integer>();
        id objrecordtypeid = [SELECT Id FROM RecordType WHERE DeveloperName ='Fund_Raising'].Id;
		double amount = 0;
        
		try {
                for (Opportunity objOpportunity : lstOpportunity){
                    oppIds.add(objOpportunity.Fund__c);
                }
            
                Fund__c objfund = [SELECT Id, Total_opportunity_amount__c  FROM Fund__c WHERE Id = :oppIds];
                List<Opportunity> list_Opportunity = [SELECT Id, Amount FROM Opportunity WHERE Fund__c = :objfund.Id and StageName = 'Closed Won' and RecordTypeId =: objrecordtypeid];
            
            
                 for(Opportunity AmountOpportunity : list_Opportunity) {
                        amount += AmountOpportunity.amount; 
                 }
            
            
                  objfund.Total_opportunity_amount__c = amount;
                  update objfund;   
            } 
       
        
        catch (Exception e) {
                System.debug(e);
            }
        
	}

}