Apex Traverse Account Hierarchy Recursively

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);
    }
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: