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.
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.