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
NikiG22NikiG22 

Rollup summary on Contact

Hello -

 

I am having some issue with adding a value on a custom object then pushing that  to a hidden field on a contact using APEX.

 

I am trying to count the number of active__c Resume_subscriptions__c on a contact. this is not a master relationship so im having issues counting the ones that are active__c only and populating the Active_Resumes__c field on the contact with the active__c count.

 

There are many code samples out there but i have no idea where to start. YOur help is Very Much Appriciated!!

 

Cheers,

Niki

Best Answer chosen by Admin (Salesforce Developers) 
Jerun JoseJerun Jose

For anyone still looking here.

The updated code is

 

trigger RollUp on Resume_Subscriptions__c (after insert, after update, before delete) {

    // Set to hold the IDs of the Contacts of the Subscriptions
    Set<ID> ContactIDs = new Set<ID>();
    // Set to hold the IDs of the Subscriptions
    Set<ID> SubIDs = new Set<ID>();
    // Set to hold the IDs of the Contacts where the values need to be reset
    Set<ID> ContactIDsForReset = new Set<ID>();

    if(trigger.isupdate || trigger.isInsert){
        for(Resume_Subscriptions__c rsSub : trigger.new ){
            // If the contact of a subscription has changed, then the old contact also needs to be updated 
            if(trigger.isUpdate)
				if( rsSub.User__c != trigger.oldmap.get(rsSub.ID).User__c)
					if(trigger.oldmap.get(rsSub.ID).User__c != null )
						ContactIDs.add(trigger.oldmap.get(rsSub.ID).User__c);
            if(rsSub.User__c!=null){
                ContactIDs.add(rsSub.User__c);
            }
        }
        ContactIDsForReset.addAll(ContactIDs);

        // The list of Contacts where the update has to take place
        List<contact> ContactsToUpdate = new List<contact>();    

        // Querying the database to get the Number of Subscriptions under an contact and the sum of the deal values of the Subscriptions under an contact
        AggregateResult[] Subscriptionsum = [select count(ID) NoOfSubscriptions, User__c ContactID from Resume_Subscriptions__c where Active__c=true AND User__c in: ContactIDs group by User__c ];
        
        for( AggregateResult ContactDetail : Subscriptionsum ){
            contact ContactToUpdate = new contact(ID = (ID)(ContactDetail.get('ContactID')));
            ContactToUpdate.Active_Resumes__c = integer.valueOf(ContactDetail.get('NoOfSubscriptions'));
            ContactsToUpdate.add(ContactToUpdate);
            // The contact being handled should not be reset. Hence removing it from the ResetSet
            ContactIDsForReset.remove((ID)(ContactDetail.get('ContactID')));
        }
        
        for( ID i : ContactIDsForReset ){
            // Resetting the summed up values to 0 if the contact no longer has a subscription.
            contact ContactToUpdate = new contact( ID = i );
            ContactToUpdate.Active_Resumes__c = 0;
            ContactsToUpdate.add(ContactToUpdate);
        }
        
        if(ContactsToUpdate.size() > 0)
            update ContactsToUpdate;
            
        ContactsToUpdate.clear();
    }

    if(trigger.isdelete){
        for(Resume_Subscriptions__c rsSub : trigger.old ){
            if( rsSub.User__c != null)
                ContactIDs.add(rsSub.User__c);
            SubIDs.add(rsSub.ID);
        }
        ContactIDsForReset.addAll(ContactIDs);

        // The list of Contacts where the update has to take place
        List<contact> ContactsToUpdate = new List<contact>();    
        
        // Querying the database to get the Number of Subscriptions under an contact excluding the Subscriptions being deleted
        AggregateResult[] Subscriptionsum = null;
        if(ContactIDs.size() > 0){
            Subscriptionsum = [select count(ID) NoOfSubscriptions, User__c ContactID from Resume_Subscriptions__c where User__c in: ContactIDs and ID not in: SubIDs group by User__c ];

            for( AggregateResult ContactDetail : Subscriptionsum ){
                contact ContactToUpdate = new contact(ID = (ID)(ContactDetail.get('ContactID')));
                ContactToUpdate.Active_Resumes__c = integer.valueOf(ContactDetail.get('NoOfSubscriptions'));
                ContactsToUpdate.add(ContactToUpdate);
                // The contact being handled should not be reset. Hence removing it from the ResetSet
                ContactIDsForReset.remove((ID)(ContactDetail.get('ContactID')));
            }

            for( ID i : ContactIDsForReset ){
                // Resetting the summed up values to 0 if the contact no longer has a subscription.
                contact ContactToUpdate = new contact( ID = i );
                ContactToUpdate.Active_Resumes__c = 0;
                ContactsToUpdate.add(ContactToUpdate);
            }
        }
        
        if(ContactsToUpdate.size() > 0)
            update ContactsToUpdate;

        ContactsToUpdate.clear();
    }
}

 

All Answers

NikiG22NikiG22

I have gotten this far: But it isnt updating my field Active_Resumes__c on my contact

 

trigger CountRelatedCallLogs_fromLog on Contact (after insert, after update) {

//Resume_Subscriptions__c are the related records
//Contact is the "main" record
//Idea is to update a field on the main record whenever an edit is made to a related record

    Contact [] scl = Trigger.new;
    String sid = null;
    sid = scl[0].id;
        
         Integer i = [select count() from Resume_Subscriptions__c where Active__c=true AND User__c = :sid]; 

        // update the master record
    Contact [] s =[select id, Active_Resumes__c from Contact where id = :sid];
 
    s[0].Active_Resumes__c = i; 
        // write to database
        update s[0];

}

 

Jerun JoseJerun Jose

Okay,

 

So a few things I want to point out..

The trigger will have to be on the child object Resume_Subscriptions__c as that is where insert and update will happen

The best way that I can think of is to use aggreate queries, as the trigger can be fired for multiple records with different contacts.

The trigger will also have to fire on delete of a child record.

Since it is a lookup field, you will also need to take care of situation where the contact alignment changes for a Resume_Subscriptions__c

 

Basically the idea is to

1. Iterate through trigger.new and collect all the Contact IDs in a set 'ContSet'

2. Issue an aggregate query to calculate the count of child records which are to the contact avaialble in ContSet.

3. Work with the query results to store the contents in a map of contact id, count..

4. Use this map to update the field value of contact.

 

Please use the below code. You might have to tweak it to work for you.

 

trigger RollUp on Resume_Subscriptions__c (after insert, after update, before delete) {

    // Set to hold the IDs of the Contacts of the Subscriptions
    Set<ID> ContactIDs= new Set<ID>();
    // Set to hold the IDs of the Subscriptions
    Set<ID> SubIDs = new Set<ID>();
    // Set to hold the IDs of the Contacts where the values need to be reset
    Set<ID> ContactIDsForReset = new Set<ID>();

    if(trigger.isupdate || trigger.isInsert)
    {
        for(Resume_Subscriptions__c rsSub : trigger.new )
        {
            // If the contact of a subscription has changed, then the old contact also needs to be updated 
            if( rsSub.Contact__c != trigger.oldmap.get(rsSub.ID).Contact__c)
                if( trigger.oldmap.get(rsSub.ID).Contact__c != null )
                    ContactIDs.add(trigger.oldmap.get(rsSub.ID).Contact__c);
            if(rsSub.Contact__c!=null)
            {
                ContactIDs.add(rsSub.Contact__c);
            }
        }
        ContactIDsForReset.addAll(ContactIDs);

        // The list of Contacts where the update has to take place
        List<contact> ContactsToUpdate = new List<contact>();    

        // Querying the database to get the Number of Subscriptions under an contact and the sum of the deal values of the Subscriptions under an contact
        AggregateResult[] Subscriptionsum = [select count(ID) NoOfSubscriptions, Contact__c ContactID from Resume_Subscriptions__c where Contact__c in: ContactIDs group by Contact__c ];
        
        for( AggregateResult ContactDetail : Subscriptionsum )
        {
            contact ContactToUpdate = new contact(ID = (ID)(ContactDetail.get('ContactID')));
            ContactToUpdate.No_of_Subscriptions__c = integer.valueOf(ContactDetail.get('NoOfSubscriptions'));
            ContactsToUpdate.add(ContactToUpdate);
            // The contact being handled should not be reset. Hence removing it from the ResetSet
            ContactIDsForReset.remove((ID)(ContactDetail.get('ContactID')));
        }
        
        for( ID i : ContactIDsForReset )
        {
            // Resetting the summed up values to 0 if the contact no longer has a subscription.
            contact ContactToUpdate = new contact( ID = i );
            ContactToUpdate.No_of_Subscriptions__c = 0;
            ContactsToUpdate.add(ContactToUpdate);
        }
        
        if(ContactsToUpdate.size() > 0)
            update ContactsToUpdate;
            
        ContactsToUpdate.clear();
	}

    if(trigger.isdelete)
    {
        for(Resume_Subscriptions__c rsSub : trigger.old )
        {
            if( rsSub.Contact__c != null)
                ContactIDs.add(rsSub.Contact__c);
            SubIDs.add(rsSub.ID);
        }
        ContactIDsForReset.addAll(ContactIDs);

        // The list of Contacts where the update has to take place
        List<contact> ContactsToUpdate = new List<contact>();    
        
        // Querying the database to get the Number of Subscriptions under an contact excluding the Subscriptions being deleted
        AggregateResult[] Subscriptionsum = null;
        if(ContactIDs.size() > 0)
        {
            Subscriptionsum = [select count(ID) NoOfSubscriptions, Contact__c ContactID from Resume_Subscriptions__c where Contact__c in: ContactIDs and ID not in: SubIDs group by Contact__c ];

            for( AggregateResult ContactDetail : Subscriptionsum )
            {
                contact ContactToUpdate = new contact(ID = (ID)(ContactDetail.get('ContactID')));
                ContactToUpdate.No_of_Subscriptions__c = integer.valueOf(ContactDetail.get('NoOfSubscriptions'));
                ContactsToUpdate.add(ContactToUpdate);
				// The contact being handled should not be reset. Hence removing it from the ResetSet
                ContactIDsForReset.remove((ID)(ContactDetail.get('ContactID')));
            }

            for( ID i : ContactIDsForReset )
            {
                // Resetting the summed up values to 0 if the contact no longer has a subscription.
                contact ContactToUpdate = new contact( ID = i );
                ContactToUpdate.No_of_Subscriptions__c = 0;
                ContactToUpdate.Total_Sum_of_Contract_Value__c = 0;
                ContactToUpdate.Contract_Billing_Retention_Status__c = 0;
                ContactsToUpdate.add(ContactToUpdate);
            }
        }
        
        if(ContactsToUpdate.size() > 0)
            update ContactsToUpdate;

        ContactsToUpdate.clear();
    }
}

 

 

 

Resume_Subscriptions__c
NikiG22NikiG22

Thank you soooo much for your help!

 

I added the code tweeked it but i get the following error:

Error: Compile Error: Incorrect SObject type: Resume_Subscriptions__c should be Contact at line 1 column 1

 

here is the modified code:

trigger RollUp on Resume_Subscriptions__c (after insert, after update, before delete) {

    // Set to hold the IDs of the Contacts of the Subscriptions
    Set<ID> ContactIDs= new Set<ID>();
    // Set to hold the IDs of the Subscriptions
    Set<ID> SubIDs = new Set<ID>();
    // Set to hold the IDs of the Contacts where the values need to be reset
    Set<ID> ContactIDsForReset = new Set<ID>();

    if(trigger.isupdate || trigger.isInsert)
    {
        for(Resume_Subscriptions__c rsSub : trigger.new )
        {
            // If the contact of a subscription has changed, then the old contact also needs to be updated 
            if( rsSub.User__c != trigger.oldmap.get(rsSub.ID).User__c)
                if( trigger.oldmap.get(rsSub.ID).User__c != null )
                    ContactIDs.add(trigger.oldmap.get(rsSub.ID).User__c);
            if(rsSub.User__c!=null)
            {
                ContactIDs.add(rsSub.User__c);
            }
        }
        ContactIDsForReset.addAll(ContactIDs);

        // The list of Contacts where the update has to take place
        List<contact> ContactsToUpdate = new List<contact>();    

        // Querying the database to get the Number of Subscriptions under an contact and the sum of the deal values of the Subscriptions under an contact
        AggregateResult[] Subscriptionsum = [select count(ID) NoOfSubscriptions, User__c ContactID from Resume_Subscriptions__c where Active__c=true AND User__c in: ContactIDs group by User__c ];
        
        for( AggregateResult ContactDetail : Subscriptionsum )
        {
            contact ContactToUpdate = new contact(ID = (ID)(ContactDetail.get('ContactID')));
            ContactToUpdate.Active_Resumes__c = integer.valueOf(ContactDetail.get('NoOfSubscriptions'));
            ContactsToUpdate.add(ContactToUpdate);
            // The contact being handled should not be reset. Hence removing it from the ResetSet
            ContactIDsForReset.remove((ID)(ContactDetail.get('ContactID')));
        }
        
        for( ID i : ContactIDsForReset )
        {
            // Resetting the summed up values to 0 if the contact no longer has a subscription.
            contact ContactToUpdate = new contact( ID = i );
            ContactToUpdate.Active_Resumes__c = 0;
            ContactsToUpdate.add(ContactToUpdate);
        }
        
        if(ContactsToUpdate.size() > 0)
            update ContactsToUpdate;
            
        ContactsToUpdate.clear();
    }

    if(trigger.isdelete)
    {
        for(Resume_Subscriptions__c rsSub : trigger.old )
        {
            if( rsSub.User__c != null)
                ContactIDs.add(rsSub.User__c);
            SubIDs.add(rsSub.ID);
        }
        ContactIDsForReset.addAll(ContactIDs);

        // The list of Contacts where the update has to take place
        List<contact> ContactsToUpdate = new List<contact>();    
        
        // Querying the database to get the Number of Subscriptions under an contact excluding the Subscriptions being deleted
        AggregateResult[] Subscriptionsum = null;
        if(ContactIDs.size() > 0)
        {
            Subscriptionsum = [select count(ID) NoOfSubscriptions, User__c ContactID from Resume_Subscriptions__c where User__c in: ContactIDs and ID not in: SubIDs group by User__c ];

            for( AggregateResult ContactDetail : Subscriptionsum )
            {
                contact ContactToUpdate = new contact(ID = (ID)(ContactDetail.get('ContactID')));
                ContactToUpdate.Active_Resumes__c = integer.valueOf(ContactDetail.get('NoOfSubscriptions'));
                ContactsToUpdate.add(ContactToUpdate);
                // The contact being handled should not be reset. Hence removing it from the ResetSet
                ContactIDsForReset.remove((ID)(ContactDetail.get('ContactID')));
            }

            for( ID i : ContactIDsForReset )
            {
                // Resetting the summed up values to 0 if the contact no longer has a subscription.
                contact ContactToUpdate = new contact( ID = i );
                ContactToUpdate.Active_Resumes__c = 0;
                ContactsToUpdate.add(ContactToUpdate);
            }
        }
        
        if(ContactsToUpdate.size() > 0)
            update ContactsToUpdate;

        ContactsToUpdate.clear();
    }
}

 

Jerun JoseJerun Jose

I have a good chance of being wrong, but maybe you cant just edit the existing trigger for this.

As we are changing the object on which we are writing the trigger.

 

You will have to go to Setup->Create->Objects->Resume_Subscriptions__c->Triggers->New

and then try pasting this code.

 

Thanks,

 

Jerun Jose

NikiG22NikiG22

Ya im special, that worked. But now im getting an error message

 

Error:Apex trigger trg_new_ResumeSubscriptionPackage caused an unexpected exception, contact your administrator: trg_new_ResumeSubscriptionPackage: execution of AfterUpdate caused by: System.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, RollUp: execution of AfterInsert caused by: System.NullPointerException: Attempt to de-reference a null object Trigger.RollUp: line 15, column 1: []: Trigger.trg_new_ResumeSubscriptionPackage: line 48, column 1

 

Thank you again for all your help

NikiG22NikiG22

I took out:

----------------------------------------------------

After Update

---------------------------------------------------

 

Not its:

---------------------------

after update, before delete

---------------------------

 

That seemed to work, i will test is and mark it if it a resolution.

Jerun JoseJerun Jose

If you are still looking for this, then yeah using oldmap on an insert trigger will be a problem.

Jerun JoseJerun Jose

For anyone still looking here.

The updated code is

 

trigger RollUp on Resume_Subscriptions__c (after insert, after update, before delete) {

    // Set to hold the IDs of the Contacts of the Subscriptions
    Set<ID> ContactIDs = new Set<ID>();
    // Set to hold the IDs of the Subscriptions
    Set<ID> SubIDs = new Set<ID>();
    // Set to hold the IDs of the Contacts where the values need to be reset
    Set<ID> ContactIDsForReset = new Set<ID>();

    if(trigger.isupdate || trigger.isInsert){
        for(Resume_Subscriptions__c rsSub : trigger.new ){
            // If the contact of a subscription has changed, then the old contact also needs to be updated 
            if(trigger.isUpdate)
				if( rsSub.User__c != trigger.oldmap.get(rsSub.ID).User__c)
					if(trigger.oldmap.get(rsSub.ID).User__c != null )
						ContactIDs.add(trigger.oldmap.get(rsSub.ID).User__c);
            if(rsSub.User__c!=null){
                ContactIDs.add(rsSub.User__c);
            }
        }
        ContactIDsForReset.addAll(ContactIDs);

        // The list of Contacts where the update has to take place
        List<contact> ContactsToUpdate = new List<contact>();    

        // Querying the database to get the Number of Subscriptions under an contact and the sum of the deal values of the Subscriptions under an contact
        AggregateResult[] Subscriptionsum = [select count(ID) NoOfSubscriptions, User__c ContactID from Resume_Subscriptions__c where Active__c=true AND User__c in: ContactIDs group by User__c ];
        
        for( AggregateResult ContactDetail : Subscriptionsum ){
            contact ContactToUpdate = new contact(ID = (ID)(ContactDetail.get('ContactID')));
            ContactToUpdate.Active_Resumes__c = integer.valueOf(ContactDetail.get('NoOfSubscriptions'));
            ContactsToUpdate.add(ContactToUpdate);
            // The contact being handled should not be reset. Hence removing it from the ResetSet
            ContactIDsForReset.remove((ID)(ContactDetail.get('ContactID')));
        }
        
        for( ID i : ContactIDsForReset ){
            // Resetting the summed up values to 0 if the contact no longer has a subscription.
            contact ContactToUpdate = new contact( ID = i );
            ContactToUpdate.Active_Resumes__c = 0;
            ContactsToUpdate.add(ContactToUpdate);
        }
        
        if(ContactsToUpdate.size() > 0)
            update ContactsToUpdate;
            
        ContactsToUpdate.clear();
    }

    if(trigger.isdelete){
        for(Resume_Subscriptions__c rsSub : trigger.old ){
            if( rsSub.User__c != null)
                ContactIDs.add(rsSub.User__c);
            SubIDs.add(rsSub.ID);
        }
        ContactIDsForReset.addAll(ContactIDs);

        // The list of Contacts where the update has to take place
        List<contact> ContactsToUpdate = new List<contact>();    
        
        // Querying the database to get the Number of Subscriptions under an contact excluding the Subscriptions being deleted
        AggregateResult[] Subscriptionsum = null;
        if(ContactIDs.size() > 0){
            Subscriptionsum = [select count(ID) NoOfSubscriptions, User__c ContactID from Resume_Subscriptions__c where User__c in: ContactIDs and ID not in: SubIDs group by User__c ];

            for( AggregateResult ContactDetail : Subscriptionsum ){
                contact ContactToUpdate = new contact(ID = (ID)(ContactDetail.get('ContactID')));
                ContactToUpdate.Active_Resumes__c = integer.valueOf(ContactDetail.get('NoOfSubscriptions'));
                ContactsToUpdate.add(ContactToUpdate);
                // The contact being handled should not be reset. Hence removing it from the ResetSet
                ContactIDsForReset.remove((ID)(ContactDetail.get('ContactID')));
            }

            for( ID i : ContactIDsForReset ){
                // Resetting the summed up values to 0 if the contact no longer has a subscription.
                contact ContactToUpdate = new contact( ID = i );
                ContactToUpdate.Active_Resumes__c = 0;
                ContactsToUpdate.add(ContactToUpdate);
            }
        }
        
        if(ContactsToUpdate.size() > 0)
            update ContactsToUpdate;

        ContactsToUpdate.clear();
    }
}

 

This was selected as the best answer