You need to sign in to do that
Don't have an account?
Jhett Jones
Trigger to update parent record when any child record is updated.
So the structure I have is this:
Record of Custom Object Type A has a related list of multiple records of Custom Object Type B.
And this is what I'm looking to do:
Object Type B has a Currency field, and Object Type A has a field that is inteded to be the Sum of that Currency field for all records in the related list. Whenever any record of Object Type B is updated, I need the Sum field on Object Type A to calculate the new sum. (Essentially it is a rollup sum, but I cannot use a rollup field because these do not have a Master-Detail relationship.)
Example:
Initial State:
Record of Custom Object Type A has a related list of multiple records of Custom Object Type B.
And this is what I'm looking to do:
Object Type B has a Currency field, and Object Type A has a field that is inteded to be the Sum of that Currency field for all records in the related list. Whenever any record of Object Type B is updated, I need the Sum field on Object Type A to calculate the new sum. (Essentially it is a rollup sum, but I cannot use a rollup field because these do not have a Master-Detail relationship.)
Example:
Initial State:
- Object Type A Record SumField = 100
- Related ObjectB Record 1 CurrencyField = 50
- Related ObjectB Record 2 CurrencyField = 30
- Related ObjectB Record 3 CurrencyField = 20
- Related ObjectB Record 2 CurrencyField is changed from 30 to 80
- Object Type A Record SumField = 150
- Related ObjectB Record 1 CurrencyField = 50
- Related ObjectB Record 2 CurrencyField = 80
- Related ObjectB Record 3 CurrencyField = 20
But, I did find an answer elsewhere and have translated it into a generic form for anyone else who needs it:
**The __c portion of the names is left off if working with a Standard Object/Field
All Answers
But, I did find an answer elsewhere and have translated it into a generic form for anyone else who needs it:
**The __c portion of the names is left off if working with a Standard Object/Field
The trigger is called when the child object in the relationship is created, updated, or deleted.
When the trigger is called, it finds the parent of the child record, then from the parent reverses direction to find the full list of child records (including the child record that started the process).
Once it has all of the children, it simply adds each of their values and stores the sum in a field on the parent.
--------------------------------------------
All of the blue text above (objects names and field names) need to be replaced with the object names and field names for your organization. The variables (e.g., po, co, amount) can be left as is and they should work.
The below code may helpful for your requirement.
trigger updateaccountfield on Contact (after insert, after update) {
List<ID> AccID = New List<ID>();
for(Contact con : Trigger.new){
if(con.Account_Name__c!=null&& con.AccountId != null){
AccID.add(con.AccountId);
}
}
List<Contact> conlist = [ select Account_Name__c from Contact where accountId in :AccID];
List<Account> accList = [SELECT Name, Contact_Name__c FROM Account WHERE id in :AccID];
for(integer i = 0 ; i < accList.size(); i++){
String address = ''+conlist[0].get('Account_Name__c');
accList[i].Contact_Name__c = address;
}
update accList;
}
Excellent solution. I have similar requirement where I have to sum up the Price amount from Child list and update in Parent Price feild, But the relationship between child and parent is Self. I have leveraged your code for my requirement... but soemthign seems not working.. I see the logs getting caputered recursively... can you please advise whats wrong in the below code?
TIA !!
trigger OpportunityCalc on Opportunity (after insert, after delete, after update) {
double amount =0;
if(Trigger.isInsert){
try {
for (Opportunity co : Trigger.new){
Opportunity po = [SELECT Id, Total_value__c FROM Opportunity WHERE Id = :co.Opp__c];
system.debug('get Parent PO'+po);
List<Opportunity> l_co = [SELECT Id, Total_value__c FROM Opportunity WHERE Opp__c = :po.Id];
system.debug('get the child '+l_co);
for(Opportunity am_co : l_co) {
amount += am_co.Total_value__c;
}
po.Total_value__c = amount;
system.debug('get the total insert '+po.Total_value__c);
update po;
}
} catch (Exception e) {
System.debug(e);
}
}
if(Trigger.isAfter) {
if(Trigger.isUpdate){
try {
for (Opportunity co : Trigger.old){
Opportunity po = [SELECT Id, Total_value__c FROM Opportunity WHERE Id = :co.Opp__c];
List<Opportunity> l_co = [SELECT Id, Total_value__c FROM Opportunity WHERE Opp__c = :po.Id];
for(Opportunity am_co : l_co) {
amount += am_co.Total_value__c;
}
po.Total_value__c = amount;
system.debug('get the total update '+po.Total_value__c);
update po;
}
} catch (Exception e) {
System.debug(e);
}
}
if(Trigger.isDelete){
try {
for (Opportunity co : Trigger.old){
Opportunity po = [SELECT Id, Total_value__c FROM Opportunity WHERE Id = :co.Opp__c];
List<Opportunity> l_co = [SELECT Id, Total_value__c FROM Opportunity WHERE Opp__c = :po.Id];
for(Opportunity am_co : l_co) {
amount += am_co.Total_value__c;
}
po.Total_value__c = amount;
system.debug('get the total delete '+po.Total_value__c);
update po;
}
} catch (Exception e) {
System.debug(e);
}
}
}
}
TK1234
This trigger goes off anytime the parent object type is updated, so I don't think you can use it as is if the parent object and child object are the same. For instance, in your case the trigger goes off when an Opportunity is updated, but the trigger itself updates an Opportunity, so it would cause the recursive loop you described.
I'd think the loop would break once it tried to run and could find no suitable parent record though.
Sorry this isn't much help, but I haven't looked at this code in almost 2 years.
I have bulkfied the after update trigger part find the code below.
trigger OpportunityCalc on Opportunity (after update) {
List<Id> Opp_CC = new list<Id>();
try {
for (Opportunity co : Trigger.old){
Opp_CC.add(co.Opp_c);
}
List<Opportunity> po = [SELECT Id, Total_value__c FROM Opportunity WHERE Id = :Opp_CC];
List<Opportunity> l_co = [SELECT Id, Total_value__c FROM Opportunity WHERE Opp__c = :po.Id];
for(Opportunity am_co : l_co) {
amount += am_co.Total_value__c;
}
po.Total_value__c = amount;
system.debug('get the total update '+po.Total_value__c);
update po;
}
catch (Exception e) {
System.debug(e);
}
Here is my test classs:
@istest
public class TestContractSourceUpdateOnOpp {
static testmethod void validateContractSource()
{
Test_SharedNewAccount.createAccount('Test Account');
// Test Creation of the Shared Account
Account acct = [SELECT Id FROM Account WHERE Name = 'Test Account' LIMIT 1];
System.Assert(acct != null, 'Account was not inserted properly!');
//create opportunity
Opportunity Op = new Opportunity(ACCOUNTID = acct.Id, Name = 'TestOp',Anticipatged_1st_Test_Season__c = 'Fall 2017',ForecastCategoryName = 'Prospect & Discovery',Imp_Case_Created__c = null ,Closed_Won_Reason__c = 'Relationships', Closed_Won_Detail__c = 'Relationship with Influencer', Region__c = 'East Enrollments' , Type = 'Renewal',Test_Alignment_Option__c = 'Other (Specify in Notes)' , StageName = 'Prospect', License_Start_Date__c = date.newInstance(2018,03,01), License_End_Date__c = date.newInstance(2018,03,31), CloseDate = Date.newInstance(2018,03,30), MAP_Growth_MAP_Skills_Implementation__c = 'Standard');
insert Op;
system.debug('Insert opportunity' + Op.Id);
system.debug('Insert opportunity' + Op.contract_Source__c);
Sales_Order__c SO = new Sales_Order__c(Name = 'Test Sales Order', Opportunity__c = Op.Id, Account__c = acct.id, Contract_Source__c = 'Test Contract Source');
insert SO;
system.debug('Sales order inserted' +SO);
Test.StartTest();
{
system.debug('Try updating Sales order with Contract Status'+SO.Contract_Source__c);
system.debug('opp contract source' + Op.Contract_Source__c);
System.assert(Op.Contract_Source__c == 'Test Contract Source');
system.debug('Catch the validation'+Op);
}
Test.StopTest();
}
}
The code which you gave was working fine. I have one more requirement with same scenario i.e, if the contact is moved from one account to other account . The field in account record need to be update . Can you give any suggestions.
Can you please help?
Thanks,
List<Account> accounts = new List<Account>();
Set<ID> accountIDs = new Set<ID>();
for(Contact con : Trigger.new){
accountIDs.add(con.AccountId);
}
for(Account acc : [select ID, Rollup_Amount__c, (select Id, Amount_X__c from Contacts) from Account where ID IN: accountIDs]){
Decimal TotalAmount = 0;
for(Contact con : acc.Contacts){
TotalAmount+=con.Amount_X__c;
}
acc.Rollup_Amount__c = TotalAmount;
accounts.add(acc);
}
update accounts;
}