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
asonimieasonimie 

Cross Object Field Update Trigger

I'm just getting into a SF admin seat so I don't have much Apex experience.

 

I want 2 fields in the opportunities object to be updated once a field in a custom object is updated.

 

When the text field in Object 1 (the custom object) is entered as complete, I need two seperate fields in the opportunity object updated.

 

I want status changed to approved and a custom checkbox to go from unchecked to checked.

 

Thanks in advance

Best Answer chosen by Admin (Salesforce Developers) 
spraetzspraetz
trigger on object1__c (before insert, before update){

  List<ID> OppIds = New List<ID>();

  for(Object1__c o : Trigger.new){
    if(o.text_field__c == 'Complete' && o.Opportunity__c != null){
      OppIds.add(o.Opportunity__c);
    }
  }

  List<Opportunity__c> oppList = [SELECT id, checkbox__c, status FROM Opportunity WHERE id in :OppIds];
  for(integer i = 0 ; i < oppList.size(); i++){
    oppList[i].checkbox__c = true;
    oppList[i].status = 'Approved';
  }

  update oppList;
}

Something like that should work.

 

All Answers

spraetzspraetz
trigger on object1__c (before insert, before update){

  List<ID> OppIds = New List<ID>();

  for(Object1__c o : Trigger.new){
    if(o.text_field__c == 'Complete' && o.Opportunity__c != null){
      OppIds.add(o.Opportunity__c);
    }
  }

  List<Opportunity__c> oppList = [SELECT id, checkbox__c, status FROM Opportunity WHERE id in :OppIds];
  for(integer i = 0 ; i < oppList.size(); i++){
    oppList[i].checkbox__c = true;
    oppList[i].status = 'Approved';
  }

  update oppList;
}

Something like that should work.

 

This was selected as the best answer
cswansoncswanson

Ryan - I'm new to APEX, I'm trying to leverage your example in a cross object update I've been asked to setup.  I have a custom object called "Pre-Sales" that is associated to the standard Opportunity object via a master detail relationship.

 

On the pre-sales object I have a field called "Client Segmentation"  (this is a picklist) that I need to copy up to the opportunity into a field called "Pre Sales Client Segmentation" (this is a text field).  I have used your example and made a few changes to the field names

 

trigger PresalesUpdateOppty on Pre_Sales__c (before insert, before update){

  List<ID> OppIds = New List<ID>();

  for(Pre_Sales__c o : Trigger.new){
    if(o.Client_Segmentation__c != null && o.Opportunity__c != null){
      OppIds.add(o.Opportunity__c);
    }
  }
  
  List<Opportunity__c> oppList = [SELECT id, Pre_Sales_Client_Segmentation__c FROM Opportunity WHERE id in :OppIds];
  for(integer i = 0 ; i < oppList.size(); i++){
    oppList[i].Pre_Sales_Client_Segmentation__c = o.Client_Segmentation__c ;
  }

  update oppList;

}

 

I get this error:

Error: Compile Error: Invalid type: Opportunity__c at line 11 column 8

 

How do I resolve this?  Is it because my association is a master/detail relationship and not a lookup?  Do I need convert the pickvalue so it can be used in a text field?

 

Thanks in advance for any help you can provide.

 

Chris

Starz26Starz26

Replace List<Opportunity__c> with List<Opportunity> at line 8

 

the __c tag is only applied to custom Objects and Opportunity is a standard Object.

cswansoncswanson

Good catch, I missed that.

 

Follow up question for you if you have a moment.  This what the trigger looks like now:

 

trigger PresalesUpdateOppty on Pre_Sales__c (before insert, before update){

  List<ID> OppIds = New List<ID>();

  for(Pre_Sales__c o : Trigger.new){
    if(o.Client_Segmentation__c != null && o.Opportunity__c != null){
      OppIds.add(o.Opportunity__c);
    }
  }
  List<Opportunity> oppList = [SELECT id, Pre_Sales_Client_Segmentation__c FROM Opportunity WHERE id in :OppIds];
  for(integer i = 0 ; i < oppList.size(); i++){
    oppList[i].Pre_Sales_Client_Segmentation__c = o.Client_Segmentation__c ;
  }

  update oppList;

}

 

I'm getting a new error now:

 

Error: Compile Error: Variable does not exist: o.Client_Segmentation__c at line 12 column 51

 

I'm not familiar with the correct syntax to in the beginning of the trigger to properly set the variable.  Could you please help with that too?

 

Thanks in advance.

 

Chris

Starz26Starz26

You cannot use "o" in the location you currently have as "o" is out of context. "o" is only in context within the for loop.

 

 as long as it meets your use case try:

 

trigger PresalesUpdateOppty on Pre_Sales__c (before insert, before update){

  List<ID> OppIds = New List<ID>();
  

  for(Pre_Sales__c o : Trigger.new){
    if(o.Client_Segmentation__c != null && o.Opportunity__c != null){
      OppIds.add(o.Opportunity__c);
    }
  }
  List<Opportunity> oppList = [SELECT id, Pre_Sales_Client_Segmentation__c FROM Opportunity WHERE id in :OppIds];

  //Assuming you will only have ONE Pre_Sales__c PER Opportunity
  Map<id,Pre_sales__c> mOpptoPS = New Map<id,Pre_Sales__c>();
   
  for(pre_Sales__c p : trigger.new)
    mOpptoPS.put(p.Opportunity__c, p);


  for(integer i = 0 ; i < oppList.size(); i++){
    oppList[i].Pre_Sales_Client_Segmentation__c = mOpptoPS.get(oPPList[i].ID).Client_Segmentation__c ;
  }

  update oppList;

}

 

If there are more than one Pre_Sales__c for an Opportunity a different approach will have to be taken. The issue is when inserting / updating more than 1 record at a time you need to make sure you are populating the correct data.

CEganCEgan

Don´t know that I can just butt in on this but request is very similar to one I have:

 

I have a custom object linked to accounts - it´s a related list on accounts - lookup relationship to accounts. My question is if there is a way to automatically change the record type of this custom object when I change the record type of the account? I don´t have much experience with triggers but am willing to try. Thank you.


cswansoncswanson

This worked perfectly, thank you for the help!

AMR27AMR27

Hey All,

 

Thanks for the help with this!  I was actually trying to write the reverse of this; custom object updated from the Opp, and finally got it thanks to this thread.

 

BUT, and there's always a but, I can't find any solid Test class code that I can look at in terms of testing a cross object field update.

 

I really don't know where to start, any help would be appreciated.

 

Here is the code if that helps:

 

Thanks in advance!

 

Alex Roth

 

trigger SetAPDealType on Accounts_Payable__c (before insert, before update) {
   
List<ID> OppIds = New List<ID>();

 for (Accounts_Payable__c a : Trigger.new){
       if (a.Name != null && a.Opportunity_Name__c != null){
       OppIds.add(a.Opportunity_Name__c);
        }
     
       List<Opportunity> apList = [SELECT id, Record_Type_Name__c, Country_Formula__c FROM Opportunity WHERE id in :OppIds];
       for(integer i = 0 ; i < apList.size(); i++){   
        a.Deal_Type__C = apList[i].Record_Type_Name__c;
        a.Country__c = apList[i].Country_Formula__c;
        
update apList;
}

}

}
sarahdevelopersarahdeveloper

I am trying something similar.  If the Opportunity Status field equals "Closed Won" then make the Account Status "Current"

I am getting the following error when making the Opp status Closed Won on save:

Error:Apex trigger AccountStatus caused an unexpected exception, contact your administrator: AccountStatus: execution of BeforeUpdate caused by: System.StringException: Invalid id: Attrition: Trigger.AccountStatus: line 7, column 1

 

The account status could be different values and they only time this works is if the value is blank.  If it is either Attrition or Prospect it gives the error.

 

ANy help would be greatly appreciated.

 

Thanks Sarah 

 

 

Here is my trigger:

 

trigger AccountStatus on Opportunity (before insert, before update){

  List<ID> OppIds = New List<ID>();

  for(Opportunity a : Trigger.new){
    if(a.stagename == 'Closed Won' ){
      OppIds.add(a.account_status__c);
    }
  }

  List<Account> oppList = [SELECT id, account_status_2__c FROM Account WHERE id in :OppIds];
  for(integer i = 0 ; i < oppList.size(); i++){
     oppList[i].account_status_2__c = 'Current';
  }

  update oppList;
}

Starz26Starz26

try:

 

trigger AccountStatus on Opportunity (before insert, before update){

  List<ID> OppIds = New List<ID>();

  for(Opportunity a : Trigger.new){
    if(a.stagename == 'Closed Won' ){
      OppIds.add(a.accountID);
    }
  }

  List<Account> oppList = [SELECT id, account_status_2__c FROM Account WHERE id in :OppIds];
  for(integer i = 0 ; i < oppList.size(); i++){
     oppList[i].account_status_2__c = 'Current';
  }

  update oppList;
}

 

sarahdevelopersarahdeveloper

Thanks That did the trick!

sarahdevelopersarahdeveloper

Does anyone have test code for this?  I am in need of some.

Thanks

Sarah

UVUV

We have cross object field update feature in Spring 12 which will be released very soon and I believe lot of such requirements can be done using that. In winter 12 it is only working for Custom-Custom relationship and In Spring 12 we would be able to use this feature for Standard-Custom as well.

Read the Notes-

http://www.salesforce.com/customer-resources/releases/

Gone SurfingGone Surfing

Hoping this is a small deviation from some of the other posts. 

I've created a button in my Case object to create a new Case (of a specific record type) .

I then put that button in the Case related list within the Opportunity object.  

When in the resulting Case edit screen, I would like to have the name of the Opportunity that I just created the case from automatically populated into the custom field called Opportunity in my Case object.  

Thanks for any help in advance. 

 

The_A-RodThe_A-Rod

Hi all,

 

i'm also totally new to Apex and am trying to leverage spraetz's template, which has been a huge help so far. (Thanks very much)

 

What I need is that whenever a custom picklist field called Software__c equals 'Fusion' and the record is updated on a custom object called User_Signature__c, a checkbox is ticked on the associated Contact called Fusion_user.

 

The code below worked first time, which seems too good to be true, so I'm worried it's executing something I can't see or haven't noticed! Does it look correct?

 

The only other thing is that after the trigger updates the Fusion_User__c field, you're directed to the Contact. I need the page to stay on the User Signature record updated. How would I do that?

 

 

 

trigger IsFusionUser on User_Signature__c (before insert, before update) {

List<ID> ContactIds = New List<ID>();

  for(User_Signature__c o : Trigger.new){
    if(o.Software__c == 'Fusion' && o.Contact__c != null){
      ContactIds.add(o.Contact__c);
    }
  }

  List<Contact> ContactList = [SELECT id, Fusion_user__c FROM Contact WHERE id in :ContactIds];
  for(integer i = 0 ; i < ContactList.size(); i++){
    ContactList[i].Fusion_user__c = true;
  }

  update ContactList;
}

Aaron BlairAaron Blair
What if you wanted to take for example two fields from the opportunity product line (Start & End "Date" field) and then update cases that are automatically created (Date fields on Child Case "Start and End"). Could you use this as a starting point or more or less template and build off of? 
sfdcChi2sfdcChi2
This was very helpful for me. thanks guys
Jem57Jem57
Hi. I'm trying to do something simliar. However, I need to compare 2 fields on 2 objects. So I need something like 
If objecta.field = objectb.field set objecta.field2
Is that possible?
Jem57Jem57
Also, these objects aren't related. And if they match I want to pull a different field from 1 of the objects into a 3rd object. Which is also not related to the object being updated. 

So, 
If Ojbecta.field = objectb.field then set objectc.field=objectb.field2. 
object a and object c are related via a lookup, but object b has no relation to either.
Mihail NicaMihail Nica
Hi there - I'm struggling to adap this code to the following scenario:

1. I have a custom lookup field to Contacts records on the Product Object
2. I have a custom email field at the Quote Line Item level
3. Whenever a new Quote Line Item level is created (i.e. Product is added to a quote), I want to pull the email value from the Product's contact to populate the Quote Line Item email field.

I have updated to the code below, but cannot get it to update...any help is greatly appreciated!
 
trigger UpdateEmail2 on QuoteLineItem (before insert, before update){

  List<ID> ProdIds = New List<ID>();
  

  for(QuoteLineItem qli : Trigger.new){
    if(qli.Current_tenant_2_email__c != null && qli.Product2Id != null){
      ProdIds.add(qli.Product2Id);
    }
  }
  List<Product2> oppList = [SELECT id, Current_tenant_2__r.Email FROM Product2 WHERE id in :ProdIds];

  //Only 1 Product per quote line item
  Map<id,QuoteLineItem> mEmailtoQLI= New Map<id,QuoteLineItem>();
   
  for(QuoteLineItem p : trigger.new)
    mEmailtoQLI.put(p.Product2Id, p);


  for(integer i = 0 ; i < oppList.size(); i++){
    oppList[i].Current_tenant_2__r.Email = mEmailtoQLI.get(oPPList[i].ID).Current_tenant_2_email__c ;
  }

  update oppList;

}

 
kriti sharan 10kriti sharan 10
One basic question.. why did we use before trigger and not after trigger?
RAVITEJA C 9RAVITEJA C 9
Hi
Iam Admin not much experience in Apex programming .so I have one cross object of trigger code and fields  can u anyone please help me that  Issue.

Regards
Raviteja