+ Start a Discussion
sroberts_MEsroberts_ME 

populating new fields using triggers

So, here's the plan. I've written two triggers, one for after update and after insert and one for before update. They look a lot like this:

 

trigger beforeCAP on Contact (before update) {
    Set<Id> accountIds = new Set<Id>();
    
    for (Contact c : Trigger.new) {
        accountIds.add(c.AccountId);
    }

    Map<Id, Account> accountsToUpdate = new Map<Id, Account>([SELECT Id, Contact_CAP_Score__c FROM Account where Id in: accountIds]);

    for (Contact c : Trigger.new) {
        Account a = accountsToUpdate.get(c.AccountId);
        a.Contact_CAP_Score__c = a.Contact_CAP_Score__c - c.Contact_CAP_Score__c;
    }
    update accountsToUpdate.values();

 

annnnd

 

trigger afterCAP on Contact (after update, after insert) {
    Set<Id> accountIds = new Set<Id>();
    
    for (Contact c : Trigger.new) {
        accountIds.add(c.AccountId);
    }

    Map<Id, Account> accountsToUpdate = new Map<Id, Account>([SELECT Id, Contact_CAP_Score__c FROM Account where Id in: accountIds]);

    for (Contact c : Trigger.new) {
        Account a = accountsToUpdate.get(c.AccountId);
        a.Contact_CAP_Score__c = a.Contact_CAP_Score__c + c.Contact_CAP_Score__c;
    }
    update accountsToUpdate.values();

 

 

Using these triggers our plan is to first deploy the after update trigger and run a mass update. This will set the initial values for account.Contact_CAP_Score. Then we will deploy the before update trigger which should appropriately handle all future edits/inserts. My question is essetially this: Do you see any major problems with this plan, and is there a better way to get the task done?

 

Thanks,

-Sam

Best Answer chosen by Admin (Salesforce Developers) 
Shashikant SharmaShashikant Sharma

Your approach is right but trigger is not I guess

 

Update your triggers 

 

trigger beforeCAP on Contact (before update) {
    Set<Id> accountIds = new Set<Id>();
    
    for (Contact c : Trigger.new) {
        accountIds.add(c.AccountId);
    }

    Map<Id, Account> accountsToUpdate = new Map<Id, Account>([SELECT Id, Contact_CAP_Score__c FROM Account where Id in: accountIds]);

    for (Contact c : Trigger.new) {
        Account a = accountsToUpdate.get(c.AccountId);
        a.Contact_CAP_Score__c = a.Contact_CAP_Score__c - c.Contact_CAP_Score__c;
        accountsToUpdate.put(a.id , a);
    }
    update accountsToUpdate.values();

added this  accountsToUpdate.put(a.id , a);

 

Change it in other one too.

All Answers

Shashikant SharmaShashikant Sharma

Your approach is right but trigger is not I guess

 

Update your triggers 

 

trigger beforeCAP on Contact (before update) {
    Set<Id> accountIds = new Set<Id>();
    
    for (Contact c : Trigger.new) {
        accountIds.add(c.AccountId);
    }

    Map<Id, Account> accountsToUpdate = new Map<Id, Account>([SELECT Id, Contact_CAP_Score__c FROM Account where Id in: accountIds]);

    for (Contact c : Trigger.new) {
        Account a = accountsToUpdate.get(c.AccountId);
        a.Contact_CAP_Score__c = a.Contact_CAP_Score__c - c.Contact_CAP_Score__c;
        accountsToUpdate.put(a.id , a);
    }
    update accountsToUpdate.values();

added this  accountsToUpdate.put(a.id , a);

 

Change it in other one too.

This was selected as the best answer
sroberts_MEsroberts_ME

I'm not sure why that is necessary, the triggers definitely update the records as it is... 

Shashikant SharmaShashikant Sharma

Yes I am not concerned about the update but I was thinking of the case where you will have say more than one contact for same account so when you loop over contact first time this will get executed

 

Account a = accountsToUpdate.get(c.AccountId);

a.Contact_CAP_Score__c = a.Contact_CAP_Score__c - c.Contact_CAP_Score__c

 

when next time you come for another contact with same account this will again execute

 

Account a = accountsToUpdate.get(c.AccountId);

//Whether it will be origianl value or one time processed value that is my concern. even though i also expect it to be a reference to map so it should automatically update in MAP also , either you test above case if it works fine with your code then no issues otherwise you have to do it as I suggested.

 

I will aslo test it at my end will let you know.

 


 

 

sroberts_MEsroberts_ME

Ah, im pretty new to salesforce and now I see what you mean. I sort of knew that triggers were set up for batch processing, but i also sorta ignored the implications involved I guess. I think you are correct here. Thanks!

Shashikant SharmaShashikant Sharma

I just verified the case in my org your code will also work

 

I run this script in system logs

Account a= new Account(Name = 'Test');
MAP<String , Account> mapA = new MAP<String , Account>();
mapA.put('a' , a);
for(Integer i = 0 ; i < 5 ;i++)
{
Account a1 = mapA.put('a' , a);
a1.Name = a1.Name+i.format();
}

system.debug(mapA + '**** mapA');

 

And it worked fine changes done in a1 got in map as a1 was mere a reference of maps Account so no iisues with your approach no issues with you code.

 

If you think your problem is resolved you can mark it as accepted solution so that others can also benifit from it.