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
Steve ThurstonSteve Thurston 

How to populate empty fields when merging records

I am writing a trigger that merges a new Lead to an existing Lead if the new Lead's email matches the existing Lead's email.  The new Lead will be submitted by a web API.  The older (Master) Lead values will be maintained.  The new Lead values will only be added to the merged record if the Master Lead's field is blank.

I am having the problem that my database.merge statement is failing, apparently because it is trying to update ALL fields on the Lead during the merge, whether they can be updated or not.  For instance, here is the current error message I'm getting:

ERROR: Unable to create/update fields: IsDeleted, Name, Address, PhotoUrl, IsConverted, CreatedDate, CreatedById, LastModifiedDate, LastModifiedById, SystemModstamp, LastViewedDate, LastReferencedDate, LastTransferDate, Lead_Timeout_In_Seconds_Formula_OLD__c, Days_Since_Creation__c, Exceeds_Timeout_Limit__c, Default_Lead_Timeout_In_Seconds__c. Please check the security settings of this field and verify that it is read/write for your profile or permission set.

I' don't want to update fields like "IsConverted", "CreatedDate", "CreatedById", etc.  And some of those fields, like "PhotoUrl", don't even exist!

I don't understand why it's trying to update fields that I can't be updated.

Originally, I had SOQL queries used to retrieve the records I needed to check as duplicates, and so those queries only included a couple fields, and I got that error on those fields.  Going online, it seemed as if I needed to query for *all* fields.  Ok, bully, I found some code online that does this, in querying for all accessible fields and adding it to the Query strings.  And now I get the above error.

In short:  nowhere online have I seen that database.merge (or just a DML merge) tries to update fields during the merge and will error out if it encounters fields that haven't been directly queried or edited.  Likewise, I don't see where I'm trying to What lucky mistake am I making that is causing this problem?

I suspect that the part of the code beginning "for(String fieldName : mapFields.keySet())" is not limited to just the accessible fields, but (a) those fields should be populated in the master, so that loop shouldn't try to update them anyway, and (b) I still don't understand why the merge statement is trying to update fields that haven't been changed in the first place!

Here's the trigger.  Sorry if it's messy:  I've pulled a big chunk of it from the web in a desparate attempt to solve the problem.
--------------------------------------

trigger mergeLeads on Lead (after insert)
{
    // Merges a new Lead with an existing Lead based on matching email addresses.
    // Old Lead is the Master Lead - New Lead information will be added to the Master Lead only where the Master Lead information is blank
   
    // Set up variables
    List<Id> triggerId = new List<Id>();
    List<String> triggerEmail = new List<String>();
   
    // Read trigger into variable(s)
    for (Lead triggerLead : Trigger.new)
        {
            triggerId.add(triggerLead.Id);
            triggerEmail.add(triggerLead.Email);            
        }
 
    // Get all Lead fields formatted for use in a SOQL query
    Map<String, Schema.SObjectField> AllLeadFields = Schema.getGlobalDescribe().get('Lead').getDescribe().SObjectType.getDescribe().fields.getMap();
 
     List<String> accessiblefields = new List<String>();
 
      for(Schema.SObjectField field : AllLeadFields.values()){
            if(field.getDescribe().isAccessible())
                accessiblefields.add(field.getDescribe().getName());
        }
 
        String allfields='';
       
        for(String fieldname : accessiblefields)
            allfields += fieldname+',';
 
        allfields = allfields.subString(0,allfields.length()-1);
 
       // Query string to get all Leads with the same email address
        String masterSOQLQuery = 'SELECT ' + allfields + ' FROM Lead WHERE Email IN:  triggerEmail ORDER BY CreatedDate';
 
        // Query string to get all Leads with the same email address excluding the Master Lead
        String duplicatesSOQLQuery = 'SELECT ' + allfields + ' FROM Lead WHERE Email IN: triggerEmail AND Id != :masterLeadID LIMIT 2';
 
        List<Lead> matchingLeads = database.query(masterSOQLQuery);
 
    Lead masterLead = matchingLeads[0];
   
    Id masterLeadID = masterLead.Id;
   
    List<Lead> duplicateLeads = database.query(duplicatesSOQLQuery);
   
    // Go through the master and duplicate record fields, and update the master record where its fields are blank, but the duplicate's is populated
   
    SObjectType leadType = Schema.getGlobalDescribe().get('Lead');
    Map<String, Schema.sObjectField> mapFields = leadType.getDescribe().fields.getMap();
   
    for(String fieldName : mapFields.keySet())
        {
            if(masterLead.get(fieldName) == null && duplicateLeads[0].get(fieldName) != null)
                {
                    masterLead.put(fieldName, duplicateLeads[0].get(fieldName));
                }
        }
   
    // Merge the records
    Database.MergeResult[] results = Database.merge(masterLead, duplicateLeads, false);
  
}