0

I want to update child record from parent record using before insert trigger. When new child record is created on account then select the parent record and update child record.

trigger UpdateChildRecord on Account ( after update ){
        LIST<Account> ac = new LIST<Account>();
        Set<Id> accountIds = new Set<Id>();
        LIST<Account> newRecordUpdatable = new LIST<Account>();
        LIST<Account> childAccounts = null;

        for(Account ac_new : trigger.new) {
            for(Account ac1_old : trigger.old) {
                if(ac_new.id == ac1_old.id){
                    childAccounts = [SELECT Name,id FROM Account WHERE ParentId = :ac_new.Id];
                    for (Account childAccount : childAccounts){
                        if(ac_new.Special__c !=ac1_old.Special__c){
                            childAccount.Special__c = ac_new.Special__c;
                        }
                        if(ac_new.Local__c !=ac1_old.Local__c){
                            childAccount.Local__c = ac_new.Local__c;
                        }
                        newRecordUpdatable.add(childAccount);
                    }
                }
                childAccounts = null;
            }
        }
        if (!newRecordUpdatable.isEmpty() ){
            update newRecordUpdatable;
        }
    }
  • avoid for inside a for loop. – user44771 Jun 16 '17 at 9:24
  • For Before Update , you won't be able to access Trigger.old – Saumya Gaikwad Jun 16 '17 at 9:32
  • Can u pls explain me in brief and write code . – Akash Mistry Jun 16 '17 at 9:50
  • no let me explain again when i create new account and when select parent account at that time my two custom field check box ("Special__c " ,"Local__c ") are update as per my parent record : Example:- Suppose in parent record Local__c is true then my child record Local__c is default true have u idea or not . – Akash Mistry Jun 16 '17 at 10:01
0

Hope this will help: I changed the variable names for better understanding the code. As i understood, you are creating a child record and you want to populate the Special__c and Local__c from the parent Account record. Here is the code accordingly!

trigger UpdateChildRecord on Account ( before insert ){
        LIST<Account> parent_acc = new LIST<Account>();
        Set<Id> accountIds = new Set<Id>();
        LIST<Account> newRecordUpdatable = new LIST<Account>();
        LIST<Account> childAccounts = null;

        for(Account child_rec : trigger.new) {
                if(child_rec.ParentId != null){
                    parent_acc = [SELECT Name,id, Special__c, Local__c FROM Account WHERE Id = :child_rec.ParentId];
                if(!parent_acc.isEmpty()){
                  for (Account parent_ac1 : parent_acc){
                        if(parent_ac1.Special__c != child_rec.Special__c)
                            child_rec.Special__c = parent_ac1.Special__c;

                        if(parent_ac1.Local__c != child_rec.Local__c)
                            child_rec.Local__c = parent_ac1.Local__c;

                        //newRecordUpdatable.add(childAccount);
                    }
                  }

                }
                //childAccounts = null;            
        }
        /*if (!newRecordUpdatable.isEmpty() ){
            update newRecordUpdatable;
        }*/
    }
  • Thanks for your reply but , how about ac1_old I got this Error : "Error: Invalid Data. Review all error messages below to correct your data. Apex trigger UpdateChildRecordBefore caused an unexpected exception, contact your administrator: UpdateChildRecordBefore: execution of BeforeInsert caused by: System.NullPointerException: Attempt to de-reference a null object: Trigger.UpdateChildRecordBefore: line 6, column 1 " – Akash Mistry Jun 16 '17 at 10:10
  • @AkashMistry, i edited my answer.... Please Review – Saumya Gaikwad Jun 16 '17 at 10:12
  • i think u forgot to declare : parent_acc – Akash Mistry Jun 16 '17 at 10:18
  • Right!. it's initialized, it's working perfectly now! – Saumya Gaikwad Jun 16 '17 at 10:19
  • Thanks saumya it's working thank you so much , Actually i'm java developer but still i am learning salesfroce from last month i have problem in trigger so can u explain me which site is best for trigger. – Akash Mistry Jun 16 '17 at 10:20
0

if you want to update newly inserted record with parent record detail then use following code

trigger AccountChildRecordUpdateTrigger on Account(before insert){

    set<Id> accountIdSet = new set<id>();
    for(Account accObj : trigger.new){

        if(accObj.ParentId != null){

            accountIdSet.add(accObj.ParentId);
        }       
    }
    map<id, Account> idVsAccountmap = new map<id, Account>();
    list<Account> accountList = [Select Id,ParentId, Special__c, Local__c From Account Where Id IN: accountIdSet ];
    for(Account accObj : accountList ){

        idVsAccountmap.put(accObj.ParentId, accObj);    
    }
    for(Account accObj : trigger.new){

        if(accObj.ParentId != null){
            accObj.Special__c  = idVsAccountmap.get(accObj.ParentId).Special__c;
            accObj.Local__c  = idVsAccountmap.get(accObj.ParentId).Local__c;
        }
    }
}
  • 1
    Answers which simply contain code are not very helpful for the OP (meaning the original poster of the question) nor for other people who may visit this question in the future. The reason is that if your code doesn't work, there's nothing to help OP figure out why it doesn't work. When I answer with a block of code, I try to go into detail about how it's different from the code that the OP is currently using, and how it solves the issue presented in the question. – Derek F Jun 16 '17 at 13:23
  • 1
    Being more specific, this answer would be improved if you were to go over why you removed the query from the inside the loops (100 query limit), the pattern you used (loop over trigger.new and add ids to a collection) to avoid the need to query inside of a loop, how you're avoiding the need for a nested loop (using a query to build a map, which can be used later), etc... – Derek F Jun 16 '17 at 13:28
0

You need to take care of following points while writing trigger, as we are dealing with multi-tenant architecture

  1. No SOQL queries in for loop
  2. Maximum usage of collection of maps and set
  3. Write your logic in the handler instead of writing in trigger itself

Below is the updated code, let me know in case of any concerns.

Trigger -

trigger UpdateChildRecord on Account (before insert){
    AccountTriggerHandler.updateChildRecords(Trigger.New);
}

Handler -

public class AccountTriggerHandler{
    public static void updateChildRecords(List<Account> newAccountList){
        Set<ID> parentIDs = new Set<ID>();
        for(Account acc : newAccountList){
            parentIDs.add(acc.ParentID);
        }

        //Here I have kept all the parent accounts in a map already which will be used further in next for loop
        Map<ID,Account> parentAccountMap = new Map<ID,Account>([SELECT Name,id FROM Account WHERE ID IN : parentIDs]);

        for(Account ac_new : newAccountList) {
            Account parentAccount = parentAccountMap.get(ac_new.ParentID);
            if(parentAccount != null){
                ac_new.Special__c = parentAccount.Special__c; 
                ac_new.Local__c = parentAccount.Local__c; 
            }
        }
    }
}
0

I think You have one parent Account, having some child records. Now you had created one Account record having same parent id..now the requirement has you need to update all child records of that parent account with newly created account details before insert..so have to maintain new object(Suppose you have inserted 10 account record at a time.if you want to update all child records with 10th account record details which is newly inserted then you have to maintain that object somewhere) use following code for above scenario....

trigger AccountChildRecordUpdateTrigger on Account(before insert){

    list<Account> updateAccountList = new list<Account>();
    map<id, list<Account>> parentIdVsAccountMap = new map<id, list<Account>>();
    for(Account accObj : trigger.new){

        if(accObj.ParentId != null){
            // For latest object
            if(parentIdVsAccountMap.containsKey(accObj.ParentId)){

                parentIdVsAccountMap.remove(accObj.ParentId);
                parentIdVsAccountMap.get(accObj.ParentId).add(accObj);              
            }
            else{

                parentIdVsAccountMap.put(accObj.ParentId, new list<Account>{accObj});
            }
        }       
    }
    map<id, list<Account>> idVsAccountmap = new map<id, list<Account>>();
    list<Account> accountList = [Select Id,ParentId, Special__c, Local__c From Account Where ParentId IN: parentIdSet ]
    for(Account accObj : accountList ){

        if(idVsAccountmap.containsKey(accObj.ParentId)){

            idVsAccountmap.get(accObj.ParentId).add(accObj);
        }
        else{

            idVsAccountmap.put(accObj.ParentId, new list<Account>{accObj});
        }
    }
    for( Id key : parentIdVsAccountMap.keySet()){

        for(Account childAcc : idVsAccountmap.get(key)){

            if( childAcc.Special__c != parentIdVsAccountMap.get(key)[0].Special__c  ){

                updateAccountList.add(childAcc);
            }
            if( childAcc.Local__c != parentIdVsAccountMap.get(key)[0].Local__c ){

                updateAccountList.add(childAcc);
            }
        }       
    }
    for(Account accObj : trigger.new){

        accObj.Special__c = updateAccountList[0].Special__c;
        accObj.Local__c = updateAccountList[0].Local__c;
    }
    if(updateAccountList.size()>0){

        update updateAccountList;
    }   
}
  • No need to sign your posts, your user card gets added below each one. – Adrian Larson Jun 16 '17 at 13:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.