I have a requirement where I need to merge accounts if a particular field 'vendor_code__c' value is duplicate across the accounts.There is also 2 condition that the :-
1st condition
Account of record type 'A' needs to be the master and record type 'B' needs to be the dupliacate.
2nd condition
If there are only Accounts of record type 'B' with Duplicate vendor codes, then the account with the oldest created date is the master and the rest of the records should be duplicate.
Here I have a working code which works fine for condition 1.I am not sure on how or where to include the second condition.PLz help!
global class BatchVendorAccountMerge implements Database.Batchable<sobject> {
global Database.QueryLocator start(Database.BatchableContext ctx) {
return Database.getQuerylocator([SELECT Id, Type, RecordTypeId, Record_Type__c, Name, MasterRecordId, Vendor_Code__c FROM Account]);
}
global void execute(Database.BatchableContext BC, List<Account> accounts ) {
// Create a map with vendor code and its account
Map<String, List<Account>> vendorAccountsToMerge = new Map<String, List<Account>>();
for (Account account : accounts) {
List<Account> accountsToMerge = vendorAccountsToMerge.get(account.Vendor_Code__c);
if (accountsToMerge == null) {
accountsToMerge = new List<Account>();
vendorAccountsToMerge.put(account.Vendor_Code__c, accountsToMerge);
}
if (accountsToMerge.size() < 2) {
accountsToMerge.add(account);
} else {
System.debug('Maximum of accounts to merge reached.');
}
}
System.debug('****vendor and acc map*** ');
System.debug(vendorAccountsToMerge);
List<account> dupacc = new list<account>();
for (String vendorCode : vendorAccountsToMerge.keySet()) {
List<Account> accountsToMerge = vendorAccountsToMerge.get(vendorCode);
if (accountsToMerge.size() > 1) {
Account masterAccount;
List<Id> duplicatedAccounts = new List<Id>();
for (Account account : accountsToMerge) {
if (account.Record_Type__c == 'A') {
if (masterAccount == null) {
masterAccount = account;
} else {
System.debug('More than one account with the record type A found. Details:');
System.debug('Account Ids: ' + masterAccount + ' ' + account.Id);
}
} else if (account.Record_Type__c == 'B') {
duplicatedAccounts.add(account.Id);
}
}
System.debug('***Master account*** ' + masterAccount);
System.debug('***Duplicated accounts*** ' + duplicatedAccounts);
Database.MergeResult[] results = Database.merge(masterAccount, duplicatedAccounts, false);
System.debug('***results merged** ' + results);
}
}
global void finish(Database.BatchableContext BC) {
}
}
Best Answer
There's more than one way to solve this problem, and you certainly could do it by iterating over the
Account
list within the trigger:Then , before performing your merge, you'd check to see if
masterAccount
was null. If so, you'd drop through to see ifcandidateMasterAccount
was not null, and if it wasn't, you'd remove it fromduplicatedAccounts
and use it as the master in your merge.Another way to approach this would be to write a small wrapper class that stores a single
Account
and implements theComparable
interface. YourcompareTo
method could then implement this logic to sort the right Account to the front of the list, comparing by record type first and then created date, and you'd find the master account by simply sorting the list and taking the first entry as master.I think there's a deeper issue with your batch class, though, and it's that you're only going to find duplicates if they happen to be in the same batch context (200 records by default). I think you're going to need to use an
ORDER BY
clause (with some logic to check for cases where Accounts with the same vendor are split across invocations) or perhaps an aggregate query.