Coding question asked by Google
Find the top most parent accountId by traversing the account hierarchy
Recursive method
public with sharing class AccountHierachy { //recursive method to find parentId of top account private Id topParentId = null; public Id getParentAccountsFromAccountId(Id accountId){ Id parentId = null; Account acc = [Select Id, Parent.Id, Parent.Parent.Id, Parent.Parent.Parent.Id, Parent.Parent.Parent.Parent.Id, Parent.Parent.Parent.Parent.Parent.Id from Account where Id=:accountId][0]; if (acc!=null) parentId = findParentFromAccountId(acc, parentId); if (parentId!=null){ topParentId = parentId; getParentAccountsFromAccountId(parentId); } return topParentId; } public Id findParentFromAccountId(Account acc, Id parentId){ //level1 if (acc.Parent.Id!=null){ parentId = acc.Parent.Id; //level2 if (acc.Parent.Parent.Id!=null){ parentId = acc.Parent.Parent.Id; //level3 if (acc.Parent.Parent.Parent.Id!=null){ parentId = acc.Parent.Parent.Parent.Id; //level4 if (acc.Parent.Parent.Parent.Parent.Id!=null){ parentId = acc.Parent.Parent.Parent.Id; //level5 if (acc.Parent.Parent.Parent.Parent.Parent.Id!=null){ parentId = acc.Parent.Parent.Parent.Parent.Parent.Id; } } } } } return parentId; } }
Batch class
global class AccountHierachyBatch implements Database.Batchable<sObject>, Database.Stateful { private static Id nextParentId; @TestVisible private static Id lastParentId; private Id parentId; private Id accountId; global AccountHierachyBatch(Id accountId){ this.accountId = accountId; } String query = 'Select Id, Parent.Id, Parent.Parent.Id, Parent.Parent.Parent.Id, Parent.Parent.Parent.Parent.Id, Parent.Parent.Parent.Parent.Parent.Id from Account'; global Database.QueryLocator start(Database.BatchableContext bc){ query+=' where Id=\''+ accountId + '\''; return Database.getQueryLocator(query); } public void execute(Database.BatchableContext bc, List<Account> accounts){ AccountHierachy accountHierachy = new AccountHierachy(); Account selectedAccount = null; if (accounts!=null && accounts.size() == 1){ selectedAccount = accounts.get(0); } Id parentId = accountHierachy.findParentFromAccountId(selectedAccount, parentId); if (parentId!=null){ nextParentId = parentId; } else { nextParentId = null; } } public void finish(Database.BatchableContext bc){ if (nextParentId!=null){ lastParentId = nextParentId; Database.executeBatch(new AccountHierachyBatch(lastParentId)); } } }
Test class
@isTest public class AccountHierachyTest { @TestSetup static void setup(){ Account a1 = new Account(Name='a1'); insert a1; Account a2 = new Account(Name='a2'); a2.ParentId = a1.Id; insert a2; Account a3 = new Account(Name='a3'); a3.ParentId = a2.Id; insert a3; Account a4 = new Account(Name='a4'); a4.ParentId = a3.Id; insert a4; Account a5 = new Account(Name='a5'); a5.ParentId = a4.Id; insert a5; Account a6 = new Account(Name='a6'); a6.ParentId = a5.Id; insert a6; Account a7 = new Account(Name='a7'); a7.ParentId = a6.Id; insert a7; Account a8 = new Account(Name='a8'); a8.ParentId = a7.Id; insert a8; Account a9 = new Account(Name='a9'); a9.ParentId = a8.Id; insert a9; Account a10 = new Account(Name='a10'); a10.ParentId = a9.Id; insert a10; } @isTest static void testFindParentFromAccountId(){ Account pAccount = [Select Id from Account where Name='a10'][0]; Id topParentId = null; Test.startTest(); AccountHierachy ah = new AccountHierachy(); topParentId = ah.getParentAccountsFromAccountId(pAccount.Id); Test.stopTest(); Account topParent = [Select Id from Account where Name='a1'][0]; System.assertEquals(topParentId, topParent.Id); } @isTest static void testFindParentFromAccountIdBatch(){ Account pAccount = [Select Id from Account where Name='a10'][0]; Test.startTest(); AccountHierachyBatch ah = new AccountHierachyBatch(pAccount.Id); Database.executeBatch(ah); Test.stopTest(); Account topParent = [Select Id from Account where Name='a1'][0]; System.assertEquals(AccountHierachyBatch.lastParentId, topParent.Id); } }
Thank you for the awesome article. I’ve come up with a solution with Queueable.
public class AccountHierachyQueueable implements Queueable{
public static Id topParentId;
public Id accountId;
public AccountHierachyQueueable(Id accountId) {
this.accountId=accountId;
}
public void execute(QueueableContext con){
Account acc = [SELECT Parent.Parent.Parent.Parent.Parent.Id,
Parent.Parent.Parent.Parent.Id, Parent.Parent.Parent.Id,Parent.Parent.Id,Parent.Id FROM Account where Id=:accountId];
Id higher5 = acc.Parent?.Parent?.Parent?.Parent?.Parent?.Id;
if(higher5!=null){
System.enqueueJob(new AccountHierachyQueueable(higher5));
}else{
Account current = acc;
while(current.parent!=null){
current = current.parent;
}
topParentId = current.Id;
}
}
}