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
RbnRbn 

Account hierarchy Util

I wanted a utility class which will give me a list of all salesforce id’s in an Account Hierarchy.
I have an hierarchy of something like below and the hierarchy can span upto many levels in Account.
 
Capital World Investors (DEMO) – Ultimate PArent
Capital Research Global Investors (DEMO) – Parent
Fidelity Management & Research (DEMO) – Child
Capital Research Market Investors (DEMO) – Parent
Fidelity Management & Research & Analytics (DEMO) – Child

Thank you
Christan G 4Christan G 4
Hi Rbn, I written code that somewhat meets your requirement. I have to figure out how I am going to loop through all the child accounts for their child accounts. Here is the code that I have written so far. I plan to update it soon:

Code Sample:
public class AccHierarchyIDs {

    public static void accHierarchyIDs (ID accID) {
        
    Set <ID> accIDs = new Set <ID>();
    
        //Evaluates all Accounts and see which ones has accID equal to its ParentID
        for (Account oneAcc :[SELECT ID, Name, ParentID ,(SELECT ID From ChildAccounts) FROM Account]) {
            
            //If equals, adds ID to accID set collection
            if (oneAcc.ParentId == accID) {
                
             accIDs.add(oneAcc.id); 
                
                //For that particular Account, evaluate if it has child accounts associated to it
                //If yes, loop through those child accounts and their IDs
                if (oneAcc.ChildAccounts.size() > 0) {
                    
                    for (Integer i = 0; i < oneAcc.ChildAccounts.size(); i++) {
                        
                        accIDs.add(oneAcc.ChildAccounts[i].id);
                        
                    }    
                    
                }
                
            }        
         }   
        
        System.debug(accIDs);
        
        }    
    }

 
RbnRbn
Thank you Christan, for taking your time and posting the snippet.

However, i have tried in my org and came up with another snippet, Let me know if you think any more enhancements can be done to this.
 
public class GBMAccountHierarchyUtil {
    public list<account> accountHierarchyList{get;private set;}
    public map<id,account> accountDetailsMap{get;private set;}
    public map<id,list<account>> parentChildLinkedListMap{get;private set;}
    public GBMAccountHierarchyUtil(){}
    public static Id getUltParentId( Id accid ){
        Boolean topLevelParent = false;
        while ( !topLevelParent ) {
            Account a = [ Select Id,ParentId From Account where Id =: accid limit 1 ];
            if ( a.ParentID != null ) {
                accid = a.ParentID;
            }
            else {
                topLevelParent = true;
            }
        }
        system.debug('@@@@@'+accid);
        return accid ; // This returns the utltimate parentid for an account
    }
    
    public static map<id,List<Account>> getAcctHierarchy(string accid){   
        Boolean endTraversing = false;
        List<id> parentIdList = new List<id>();
        List<account> acctList = new list<account>();
        List<account> accountHierarchyList = new List<account>();
        Map<id,integer> accountIdLevelMap = new map<id,integer>();
        map<id,account> accountDetailsMap = new map<id,account>();
        Map<id,list<account>> parentChildLinkedListMap = new map<id,list<account>>();
        Integer accountLevel = 0;   
        parentIdList.add(accid);
        while(!endTraversing) {
            if(accountLevel == 0) {
                acctList = [SELECT Id, Name, ParentId FROM Account WHERE Id IN :parentIdList];
            } else {
                acctList = [SELECT Id, Name, ParentId FROM Account WHERE ParentId IN :parentIdList];
            }
            if(acctList.size() == 0 ) {
                endTraversing = true;
            }
            else {
                parentIdList.clear();
                Account a;
                for(Integer i = 0; i < acctList.size(); i++ ) {
                    a = acctList.get(i);
                    parentIdList.add(a.Id);
                    accountIdLevelMap.put(a.Id, accountLevel);
                    accountDetailsMap.put(a.Id, a);
                    if(accountLevel > 0) {
                        if(parentChildLinkedListMap.get(a.ParentId) == null) {
                            parentChildLinkedListMap.put(a.ParentId, new List<account>()); 
                        }
                        parentChildLinkedListMap.get(a.ParentId).add(a);
                        system.debug('@@@@@Parentchildlist' + parentChildLinkedListMap); 
                    }
                }	
            }
            accountLevel++;
        }
        return parentChildLinkedListMap;
    }
}

My Resultant output is something like this.
 
@@@parentChildList{0016300000fUx0JAAS=
(Account:{Id=0016300000fUx1KAAS,Name=Global Media (Sample),ParentId=0016300000fUx0JAAS, RecordTypeId=0122E000000l9e4QAA, CurrencyIsoCode=CAD}), 0016300000fUx1KAAS=(
Account:{Id=0016300000fUx1JAAS, Name=Acme (Sample), ParentId=0016300000fUx1KAAS, RecordTypeId=0122E000000l9e4QAA, CurrencyIsoCode=CAD}, 
Account:{Id=0016300000fUx1LAAS, Name=salesforce.com (Sample), ParentId=0016300000fUx1KAAS, RecordTypeId=0122E000000l9e4QAA, CurrencyIsoCode=CAD})}

Let me know if it makes sense.
Christan G 4Christan G 4
Hi Rbn, I hope are well. I think your code is awesome! I didn't see any issues so far when reviewing it. I guess my only concern is the possbility of reaching SOQL governor limits in the future as accounts get more and more child accounts associated to them. I may still try to create my own version by somehow using the ChildAccounts but I think your code is fulfills your requirement so far. Awesome again!
RbnRbn
Thank you Christan. Thanks for reviewing the code. Even i am also in the perception that it might hit the governor limit. However will try to optimize the code and will keep you posted.

And thanks to you for giving me a initial headup on the code snippet. Appreciated!!!

Regards,
Rabin
Christan G 4Christan G 4
Hi Rabin, I was able to update and optimize the code I written earlier. It is not as sophisticated as yours just yet lol. I have referenced some of the logic you used in your code. I plan to work on it further soon. As of now, it successfully retrieves all the related Account IDs within a hierarchy. Now I just have to work on how to display the results:

Code:
public class AccHierarchyIDs {

    public static void accHierarchyIDs (ID accID) {
    
    ID initialID = accid;    
    Set <ID> childIDs = new Set <ID>();
    Set <ID> queryIDs = new Set <ID>();    
    Boolean parentIDReroll = false;  
    Account ultimateAcc;
    Map <ID, List <Account>> childMap = new Map <ID, List <Account>>();
        
    while (!parentIDReroll) {   
    Account accIDList = [SELECT ID, Name, ParentID ,(SELECT ID From ChildAccounts) FROM Account WHERE ID =:accID];
     
         If (accIDList.parentID != null) {
             
         	accID = accIDList.ParentID;
             
         }
         
         else { parentIDReroll = true; 
                ultimateAcc = accIDList;}

         }  
  
            if (ultimateAcc.ChildAccounts.size() > 0) {
                
                for (Integer i = 0; i < ultimateAcc.ChildAccounts.size(); i++) {
                    
                    childMap.put(accid, ultimateAcc.ChildAccounts);
                    childIDs.add(ultimateAcc.ChildAccounts[i].id);
                    queryIDs.add(ultimateAcc.ChildAccounts[i].id);
                    
                }
            
                
        while (queryIDs.size() > 0) {
                    
        List <Account> childAccount = [SELECT ID, Name, ParentID ,(SELECT ID From ChildAccounts) FROM Account WHERE ID IN :queryIDs];        
        queryIDs.clear();
                
            for (Account oneAcc: childAccount) {
            
                if (oneAcc.ChildAccounts.size() > 0) {
                    
                    childMap.put(oneAcc.id, oneAcc.ChildAccounts);
                    
                    for (Integer i = 0; i < oneAcc.ChildAccounts.size(); i++) {
                    
                    childIDs.add(oneAcc.ChildAccounts[i].id);    
                    queryIDs.add(oneAcc.ChildAccounts[i].id);
                        
                    }  
                  }    
                }        
              }
            }
        
        System.debug(childIDs);
        
          }
        }