0

I'm working on a batch that inserts members to a campaign, the insertion is done with a csv file.

Now i have been trying to handle any duplicate values as well, to avoid errors but mostly i would like to be able to update these
duplicate records by retrieving them and updating their status.

I ran this code :

private void insertRecords(Map<Integer, SObject> records, Map<String, SObject> recordsToUpdate, Map<Integer, Object> recordsByRows) {
        Integer index = 0;
        Database.SaveResult[] insertSaveResults = Database.insert(records.values(), false);
        for (Database.SaveResult sr : insertSaveResults) {
            SObject currentRecord = records.values().get(index);
            if (sr.isSuccess()) {
                successRecords.add(currentRecord);
            } else {
                for (Database.Error error : sr.getErrors()) {
                    System.debug('### ' + CLASS_NAME + ' - Error Delete:'+error.getMessage());
                    if (error instanceof Database.DuplicateError) {
                        Database.DuplicateError duplicateError = (Database.DuplicateError) error;
                        for (Datacloud.MatchResult matchResult : duplicateError.getDuplicateResult().getMatchResults()) {
                            if (matchResult.getEntityType() == String.valueOf(currentRecord.getSObjectType())) {
                                SObject matchRecord = matchResult.getMatchRecords()[0].getRecord();
                                currentRecord.put('Id', matchRecord.Id);
                                if (!recordsToUpdate.containsKey(matchRecord.Id)) {
                                    recordsToUpdate.put(matchRecord.Id, currentRecord);
                                }
                            }
                        }
                    } else {
                        ExcelToRecords.createErrorRecord(recordsByRows, index, error.getMessage(), errors);
                    }
                }
            }
            index++;
        }
    }
private void updateRecords(Map<String, SObject> recordsToUpdate, Map<Integer, SObject> records, Map<Integer, Object> recordsByRows) {
        Integer index = 0;


        if (!recordsToUpdate.isEmpty()) {
            Database.SaveResult[] updateSaveResult = Database.update(recordsToUpdate.values(), false);
            for (Database.SaveResult sr : updateSaveResult) {
                SObject currentRecord = records.values().get(index);
                if (sr.isSuccess()) {
                    updatedRecords.add(currentRecord);
                } else {
                    for (Database.Error error : sr.getErrors()) {
                        //ExcelToRecords.createErrorRecord(recordsByRows, index, error.getMessage(), errors);
                    }
                }
                index++;
            }
        }

But I could not get the desired result.

It would appear that the 'if in question : if (error instanceof Database.DuplicateError)

does not function correctly.

I also tried to create a duplicate rule but it would seem to be effective only with regard to duplicate leads and not contacts.

1 Answer 1

1

Database.DuplicateError is only for Duplicate Rules. Instead, you can check getStatusCode on the error and compare it with StatusCode.DUPLICATE_VALUE. However, that still won't tell you which record it duplicates with, so you'd have to query the database to find those records.

Notably, this means you can't use this generic code to try and deal with standard duplicate validations. Write a proper method that handles these directly by first querying for existing campaign members, putting them into a map, and then using upsert:

Set<Id> recordIds = new Set<Id>();
for(CampaignMember member: records.values()) {
  recordIds.add(member.LeadId);
  recordIds.add(member.ContactId);
  recordIds.add(member.CampaignId);
}
Map<CampaignMember, CampaignMember> existing = new Map<CampaignMember, CampaignMember>();
for(CampaignMember member: [
  SELECT CampaignId, LeadId, ContactId 
  FROM CampaignMember 
  WHERE (LeadId = :recordIds OR ContactId = :recordIds) AND CampaignId = :recordIds]) {
  if(member.ContactId != null) {
    existing.put(new CampaignMember(ContactId=member.ContactId, CampaignId=member.CampaignId), member);
  } else {
    existing.put(new CampaignMember(LeadId=member.LeadId, CampaignId=member.CampaignId), member);
  }
}
for(Integer index: records.keySet()) {
  CampaignMember tempMember = records.get(index);
  CampaignMember leadKey = new CampaignMember(LeadId=tempMember.LeadId, CampaignId=member.CampaignId);
  CampaignMember contactKey = new CampaignMember(ContactId=tempMember.ContactId, CampaignId=member.CampaignId);
  CampaignMember leadTest = existing.get(leadKey);
  CampaignMember contactTest = existing.get(contactKey);
  if(leadTest != null) {
    tempMember.Id = leadTest.Id;
  }
  if(contactTest != null) {
    tempMember.Id = contactTest.Id;
  }
}
CampaignMember[] recordsToUpsert = records.values();
recordsToUpsert.sort(); // Put inserts and updates next to each other
Database.UpsertResult[] results = Database.upsert(recordsToUpsert, false);

Finally, after all that, proceed to process the results for any other errors.

You must log in to answer this question.

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