0

Objects : Lead(Parent record),LeadClientInsurance__c (Related records) if I change the First_Name__c in LeadClientInsurance__c object I need to change FirstName in Lead Record.

Theoretically, LeadClientInsurance__c.First_Name__c == Lead.FirstName

If I change LeadClientInsurance__c's First_Name__c, the Lead's FirstName needs to be changed. I need an Apex trigger to work in both ways – if the Lead's FirstName is changed, LeadClientInsurance__c's First_Name__c needs to be changed

enter image description here

enter image description here

3
  • Welcome to SFSE! Please take the tour and read How to Ask. You should edit your question to show us what you've tried and point out where you're stuck. If you're new to Salesforce (or just a part/feature thereof, like triggers) then trailhead.salesforce.com is going to be a better resource to help get you started.
    – Derek F
    Nov 19, 2023 at 15:49
  • I will say that bi-directional data updates like this tend to result in infinite loops. Using a formula field to pull the name from the parent Lead could save you a bit of trouble in that regard. Otherwise you'd need an additional Apex class with a static variable (static variables defined within a trigger are valid syntax but functionally useless) to help you avoid that. The simplest pattern that doesn't immediately break bulk operation being setting a static variable just before the problematic DML statement, and unsetting the static var right after the problematic DML.
    – Derek F
    Nov 19, 2023 at 16:01
  • @DerekF Proper implementations don't create infinite loops. It takes just a few extra lines of code to prevent such loops. It is entirely possible to create a bidirectional update without infinite recursion without using static variables, etc.
    – sfdcfox
    Nov 19, 2023 at 17:14

1 Answer 1

0

You'll want to write two triggers, one for Lead and LeadClientInsurance__c. Both will look very similar. You can also build this design in a flow, but I'm not going to build all that for this question. Just know that it involves the exact same steps: get the related record, check if the values don't match, and if not, then perform an update.

What follows are the most simple trigger implementations to help you get started.

Lead Trigger v1

trigger Lead on Lead (after update) {
  // Get child records
  LeadClientInsurance__c[] leadClientInsurances = [
    SELECT Lead__c, First_Name__c
    FROM LeadClientInsurance__c
    WHERE Lead__c = :Trigger.new
  ];
  LeadClientInsurance__c[] updates = new LeaderClientInsurance__c[0];
  // For each child record, if does not match, update.
  for(LeadClientInsurance insuranceRecord: leadClientInsurances) {
    Lead leadRecord = Trigger.newMap.get(insuranceRecord.Lead__c);
    if(insuranceRecord.FirstName != insuranceRecord.First_Name__c) {
      updates.add(new LeaderClientInsurance__c(
        Id=insuranceRecord.Id,
        First_Name__c=leadRecord.FirstName
      ));
    }
  }
  // update lead client insurance records
  update updates;
}

Lead Client Insurance Trigger v1

trigger LeadClientInsurance on LeadClientInsurance__c (after insert, after update) {
  // Get parent records
  Map<Id, Lead__c> leadRecords = new Map<Id, Lead__c>([
    SELECT FirstName
    FROM Lead
    WHERE Id IN (SELECT Lead__c FROM LeadClientInsurance__c WHERE Id = :Trigger.new)
  ]);
  Map<Id, Lead__c> updates = new Map<Id, Lead__c>();
  // If changed, add to updates map
  for(LeadClientInsurance__c insuranceRecord: Trigger.new) {
    Lead leadRecord = leadRecords.get(insuranceRecord.Lead__c);
    if(leadRecord.FirstName != insuranceRecord.First_Name__c) {
      updates.put(insuranceRecord.Lead__c, new Lead__c(
        Id=insuranceRecord.Lead__c,
        FirstName=insuranceRecord.First_Name__c
      ));
    }
  }
  // update leads
  update updates.values();
}

An alternative arrangement checks if the field has changed first, and then makes an update for records that don't have the correct value. This code is slightly better for performance if you know all your data is in sync. Unless you have significant resource usage already, though, I'd probably go with the design above.

Lead Trigger v2

trigger Lead on Lead (after update) {
  Set<Id> leadIds = new Set<Id>();
  for(Integer i = 0; i < Trigger.size(); i++) {
    if(Trigger.old[i].FirstName != Trigger.new[i].FirstName) {
      leadIds.add(Trigger.new[i].Id);
    }
  }
  if(leadIds.isEmpty()) {
    return;
  }
  LeadClientInsurance__c[] updates = new LeaderClientInsurance__c[0];
  for(LeadClientInsurance__c insuranceRecord : [
    SELECT First_Name__c, Lead__c
    FROM LeadClientInsurance__c
    WHERE Lead__c = :leadIds
  ]) {
    Lead leadRecord = Trigger.newMap.get(insuranceRecord.Lead__c);
    if(leadRecord.FirstName != insuranceRecord.First_Name__c) {
      updates.add(
        new LeaderClientInsurance__c(
          Id=insuranceRecord.Id, 
          First_Name__c=leadRecord.FirstName
        )
      );
    }
  }
  update updates;
}

Lead Client Insurance Trigger v2

trigger LeadClientInsurance on LeadClientInsurance__c (after insert, after update) {
  Map<Id, Lead> leadRecords = new Map<Id, Lead>();
  Map<Id, Lead> updates = new Map<Id, Lead>();
  for(Integer i = 0; i < Trigger.size(); i++) {
    if(Trigger.old[i].First_Name__c != Trigger.new[i].First_Name__c) {
      leadRecords.put(Trigger.new[i].Lead__c, null);
    }
  }
  if(leadRecords.isEmpty()) {
    return;
  }
  leadRecords.putAll([SELECT FirstName FROM Lead WHERE Id = :leadRecords.keySet()]);
  for(LeadClientInsurance__c insuranceRecord: Trigger.new) {
    Lead leadRecord = leadRecords.get(insuranceRecord.Lead__c);
    if(leadRecord != null && leadRecord.FirstName != insuranceRecord.First_Name__c) {
      updates.put(new Lead(
        Id=leadRecord.Id,
        FirstName=insuranceRecord.First_Name__c
      ));
    }
  }
}

Other arrangements are possible as well. For example, we can make this code more efficient by using a common class to hold data so we don't have to use extra queries, or make it dynamic for which fields we want to map, and so on.

At any rate, this code isn't meant to be production ready. A proper solution should include error handling, support partial success updates, a trigger handler framework for testing and maintenance purposes, and so on. These are minimum implementation solutions designed to show how to deal with bidirectional field updates in Apex code.

2
  • Hi, Mr.sfdcfox Thank you so much! , Can you explain how to add more fields like LastName , MIddleName,Date_Of_Birth , Suffix, Email , Phone like that. Nov 19, 2023 at 18:49
  • @PamodaWijesinghe Add the fields to check into the query, and then check all of the fields to see if any have changed (if(ir.field1 != lr.field1 || ir.field2 != lr.field2 || ir.field3 != lr.field3 ...), and add those fields to the new Lead and new LeadClientInsurance__c statements. The rest of the process remains the same.
    – sfdcfox
    Nov 19, 2023 at 19:40

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .