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
matthew_hicks_1matthew_hicks_1 

Trigger to update a lookup field on Account object

Hi All, I trying to write my first trigger, failing hard. I would really appreciate any help.  Thank you, Matt

My Scenario: 
I have a custom object named Commerciant Customer Record that has a lookup field for Accounts. Every Account only has 1 Commerciant Customer Record that is imported into Salesforce. I have a lookup field on my Account object named Syspro Customer Record that needs to be passed the Id of the Commerciant Customer Record so I can link the two and write field formulas. Below are my field names and my trigger, I do not get any errors when saving it. Is my logic off and why does nothing happen when I create a new Commerciant Customer Record and link it to an account. 

Account = my parent object
Commerciant Customer Record (CommercientSF__ArCustomer__c) = child object
CommercientSF__AccountID__c = Lookup(Account) on Commerciant Customer Record Object
Syspro_Customer_Record__c = Lookup(Commerciant Customer Record) on Account object (the field I am trying up update)

trigger CustomerID on Account(after insert) {
if(trigger.isInsert)
  {
    set<Id> custId = new set<ID>();
    for(Account a : Trigger.New)
    {
       custID.add(a.Syspro_Customer_Record__c);
    }
    Map<Id, Id> custToAccountMap = new Map<Id, Id>();
    for(CommercientSF__ArCustomer__c c :[select Id, CommercientSF__AccountID__c from CommercientSF__ArCustomer__c where id in: custID])
    {
       custToAccountMap.put(c.id,c.CommercientSF__AccountID__c);
    }
    for(Account a: trigger.new)
    {
       a.Syspro_Customer_Record__c = custToAccountMap.get(a.Syspro_Customer_Record__c);
    }
   }
}


Best Answer chosen by matthew_hicks_1
Vi$hVi$h
Hi Matthew, 

Yes you are right , it wont work on after insert for account.
Ignore the previous code..
Few things to consider 
1.You have look up from your custom object to Account
2. You have a lookupfrom Account to your custom object 
Why woud you do so ??

Even then if we populate the Syspro_Customer_Record__c field on account , what when someone updates the custom object record and changes the account look up value,you will have to delete the Syspro_Customer_Record__c value in the account to which was previously updated.
Add the Syspro_Customer_Record__c value in the new account as well.

I have corrected the code and written it on after insert after update on the custom object:
trigger CustomerID on CommercientSF_ArCustomer__c(after insert,after update) {
    //CommercientSF__AccountID__c //look up on account
    //Syspro_Customer_Record__c //look up from account to fill this
    
    Map<Id, Id> MapAccCom = new Map<Id, Id>();
    for(CommercientSF_ArCustomer__c comm:trigger.new)
    {
        MapAccCom.put(comm.CommercientSF_AccountID__c,comm.id);
    
    }
    
    List<Account> accounts = [Select id from Account where id IN :MapAccCom.keyset()];
    List<Account> AccList = new List<Account>();
    for(Account acc : accounts)
    {
        acc.Syspro_Customer_Record__c = MapAccCom.get(acc.id);
        AccList.add(acc);
    }
    
    update AccList;
}
This code is just an answer to the question you presented but it does not cover all the scenarios.

Thanks,
Vishal Shinde

All Answers

Vi$hVi$h
You want to populate Syspro_Customer_Record__c, but the set you create custID consists of this field itself.
Assuming there is no value in it, the rest of the code wont work.

I have made some changes in your code: 

trigger CustomerID on Account(after insert) {
if(trigger.isInsert)
  {
    set<Id> custId = new set<ID>();
    for(Account a : Trigger.New)
    {
       custID.add(a.id); // get all the account ids
    }
    Map<Id, Id> custToAccountMap = new Map<Id, Id>();
    for(CommercientSF__ArCustomer__c c :[select Id, CommercientSF__AccountID__c from CommercientSF__AccountID__c where id in: custID])
    {
       custToAccountMap.put(c.CommercientSF__AccountID__c,c.id);//create a map with account ID as the key and CommercientSF__ArCustomer__c as value
    }
    for(Account a: trigger.new)
    {
       a.Syspro_Customer_Record__c = custToAccountMap.get(a.CommercientSF__AccountID__c); // fetch CommercientSF__ArCustomer__c value
    }
   }
}

Hope this helps.
Thanks,
Vishal
matthew_hicks_1matthew_hicks_1
I really appreciate your help Vishal. When I add a.CommercientSF_AccounttID__c to line below I get the error Compile Error: Invalid field CommercientSF__AccountID__c for SObject Account at line 16 column 59.

a.Syspro_Customer_Record__c = custToAccountMap.get(a.CommercientSF__AccountID__c); // fetch CommercientSF__ArCustomer__c value

It seems that it is looking for the CommercientSF__AccountID__c from the Account object,  but CommercientSF__AccountID__c is my Lookup(Account) field on my Commerciant Customer Record object. Any idea why I am getting that error? Below is my code with your updated changes:

trigger CustomerID on Account(after insert) {
if(trigger.isInsert)
  {
    set<Id> custId = new set<ID>();
    for(Account a : Trigger.New)
    {
       custID.add(a.id);
    }
    Map<Id, Id> custToAccountMap = new Map<Id, Id>();
    for(CommercientSF__ArCustomer__c c :[select Id, CommercientSF__AccountID__c from CommercientSF__ArCustomer__c where id in: custID])
    {
       custToAccountMap.put(c.CommercientSF__AccountID__c,c.id);
    }
    for(Account a: trigger.new)
    {
       a.Syspro_Customer_Record__c = custToAccountMap.get(a.CommercientSF__AccountID__c);
    }
   }
}
matthew_hicks_1matthew_hicks_1
One more thing to note is that the Account is created first and then the Commerciant Customer Record is created with the lookup to the account. Is After Insert the right trigger?
Vi$hVi$h
Hi Matthew, 

Yes you are right , it wont work on after insert for account.
Ignore the previous code..
Few things to consider 
1.You have look up from your custom object to Account
2. You have a lookupfrom Account to your custom object 
Why woud you do so ??

Even then if we populate the Syspro_Customer_Record__c field on account , what when someone updates the custom object record and changes the account look up value,you will have to delete the Syspro_Customer_Record__c value in the account to which was previously updated.
Add the Syspro_Customer_Record__c value in the new account as well.

I have corrected the code and written it on after insert after update on the custom object:
trigger CustomerID on CommercientSF_ArCustomer__c(after insert,after update) {
    //CommercientSF__AccountID__c //look up on account
    //Syspro_Customer_Record__c //look up from account to fill this
    
    Map<Id, Id> MapAccCom = new Map<Id, Id>();
    for(CommercientSF_ArCustomer__c comm:trigger.new)
    {
        MapAccCom.put(comm.CommercientSF_AccountID__c,comm.id);
    
    }
    
    List<Account> accounts = [Select id from Account where id IN :MapAccCom.keyset()];
    List<Account> AccList = new List<Account>();
    for(Account acc : accounts)
    {
        acc.Syspro_Customer_Record__c = MapAccCom.get(acc.id);
        AccList.add(acc);
    }
    
    update AccList;
}
This code is just an answer to the question you presented but it does not cover all the scenarios.

Thanks,
Vishal Shinde
This was selected as the best answer
matthew_hicks_1matthew_hicks_1
Thanks Vishal, I was looking at the trigger backwards. In order for me to push up the field to the account I needed to set that trigger on the custom object rather than my Account object. My last question about best practices. 

Is it better to create a lookup field to a child object (in my case Syspro_Customer_Record__c) and create new formula fields to rollup information (see pic) or is it best practice to create new text, number, date etc... fields and use a trigger to rollup information into those fields?  Thank you for all your help!

User-added image


Vi$hVi$h
Using the formula field would be better.
Advantages of using a formula field:
1. You wont need to write any code !
2. No code coverage as well.
3. The formula fields will be uneditable.

Thanks,
Vishal Shinde