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
SFDCDevQASFDCDevQA 

Querying Territories on Account record

I'm trying to Query all of the Territories associated with an account record (old Territory not Territory2) in order to put them in a custom text field. First I am trying to do the steps of going from Account to AccountShare to Group to Territory but based on my debug it seems to be breaking from going from the list to the map on AccountShares.  The the debug list shows all the AccountShares that it should when I test update an account but then the debug on the map for Account shares only shows one AccountShare and not the correct one.  So once that map only gives one then all the rest only give one.  Can someone direct me as to what I'm doing wrong that is causing the map of the list to vary from the list itself?
Thanks

trigger AccountTerritories on Account (before update){
    if(Trigger.isBefore){
        Set<Id> setOfAccountIds = new Set<Id>();

        for(Account acct : Trigger.New){
            if(Trigger.isUpdate){
                if(acct.Id != null){
                    setOfAccountIds.add(acct.Id);
                }
            }
        }
 
        if(setOfAccountIds.size() > 0){

        /* Declaration of collection data types */
Map<Id, Id> mapOfAccountShare = new Map<Id, Id>();
       Map<Id, Id> mapOfGroup = new Map<Id, Id>();
       Map<Id, Territory> mapOfUserTerritory = new Map<Id, Territory>();


//Query in Account Share object

    List<AccountShare> listOfAccountShare =
    [Select Id, UserOrGroupId, AccountId, RowCause from AccountShare where AccountId IN :setOfAccountIds];
    System.debug('=== contents of listOfAccountShare: ' + listOfAccountShare);

//Map of Account Share
    for(AccountShare acctShare : listOfAccountShare){
    mapOfAccountShare.put(acctShare.AccountId, acctShare.UserOrGroupId);        
    }      
    System.debug('=== all AccountShare keys in the map: ' + mapOfAccountShare.keySet());  
    System.debug('=== all AccountShare values in the map (as a List): ' + mapOfAccountShare.values());

    //Query in Group object            
    List<Group> listOfGroup = [Select Id, RelatedId from Group where Type='Territory' and Id IN :mapOfAccountShare.Values()];
    System.debug('=== contents of listOfGroup: ' + listOfGroup);
//Map of Group object
    for(Group groupRecord : listOfGroup){
    mapOfGroup.put(groupRecord.Id, groupRecord.RelatedId);        
    }
    System.debug('=== all Group keys in the map: ' + mapOfGroup.keySet());  
    System.debug('=== all Group values in the map (as a List): ' + mapOfGroup.values());

    //Query in Territory object
    Map<Id, Territory> mapOfTerritories =
    new Map<Id, Territory>([select id, name, ParentTerritoryId from Territory where Id IN:mapOfGroup.Values() ]);  
    System.debug('=== all Territories keys in the map: ' + mapOfTerritories.keySet());  
    System.debug('=== all Territories values in the map (as a List): ' + mapOfTerritories.values());  


 
}

}
}

 
Best Answer chosen by SFDCDevQA
Vishal_GuptaVishal_Gupta
Hi,

Please use below code, it will work for you.

trigger AccountTerritories on Account (before update){
    if(Trigger.isBefore){
        Set<Id> setOfAccountIds = new Set<Id>();

        for(Account acct : Trigger.New){
            if(Trigger.isUpdate){
                if(acct.Id != null){
                    setOfAccountIds.add(acct.Id);
                }
            }
        }
 
        if(setOfAccountIds.size() > 0){

        /* Declaration of collection data types */
Map<Id, Id> mapOfAccountShare = new Map<Id, Id>();
       Map<Id, Id> mapOfGroup = new Map<Id, Id>();
       Map<Id, Territory> mapOfUserTerritory = new Map<Id, Territory>();


//Query in Account Share object

    List<AccountShare> listOfAccountShare =
    [Select Id, UserOrGroupId, AccountId, RowCause from AccountShare where AccountId IN :setOfAccountIds];
    System.debug('=== contents of listOfAccountShare: ' + listOfAccountShare);

//Map of Account Share
    for(AccountShare acctShare : listOfAccountShare){
    mapOfAccountShare.put(acctShare.Id, acctShare.UserOrGroupId);        
    }      
    System.debug('=== all AccountShare keys in the map: ' + mapOfAccountShare.keySet());  
    System.debug('=== all AccountShare values in the map (as a List): ' + mapOfAccountShare.values());

    //Query in Group object            
    List<Group> listOfGroup = [Select Id, RelatedId from Group where Type='Territory' and Id IN :mapOfAccountShare.Values()];
    System.debug('=== contents of listOfGroup: ' + listOfGroup);
//Map of Group object
    for(Group groupRecord : listOfGroup){
    mapOfGroup.put(groupRecord.Id, groupRecord.RelatedId);        
    }
    System.debug('=== all Group keys in the map: ' + mapOfGroup.keySet());  
    System.debug('=== all Group values in the map (as a List): ' + mapOfGroup.values());

    //Query in Territory object
    Map<Id, Territory> mapOfTerritories =
    new Map<Id, Territory>([select id, name, ParentTerritoryId from Territory where Id IN:mapOfGroup.Values() ]);  
    System.debug('=== all Territories keys in the map: ' + mapOfTerritories.keySet());  
    System.debug('=== all Territories values in the map (as a List): ' + mapOfTerritories.values());  
}
}
}

Please let me know if I can help you more.

Thanks,
Vishal

All Answers

Vishal_GuptaVishal_Gupta
Hi,

Please replace your debugs with below ones, sometimes debug only show one record values so its better to check the size of list, I don't see any flaw in your code .

-->  System.debug('=== contents of listOfAccountShare: ' + listOfAccountShare.size());
--> System.debug('=== all AccountShare keys in the map: ' + mapOfAccountShare.size());  
--> System.debug('=== all Group keys in the map: ' + mapOfGroup.keySet().size());
-->  System.debug('=== all Territories keys in the map: ' + mapOfTerritories.size());  

Please let me know if I can help you more.

Thanks,
Vishal
SFDCDevQASFDCDevQA
I added the size but the numbers are all wrong.  It lists out only 10 in the listOfAccountShare but size of the list says 17.  Then the map only says 1 even though there are clearly at least 10 different group IDs and the group ID it gives is not even one that was in the prior list AND the number of territories shown on the account itself is 9....

|DEBUG|=== contents of listOfAccountShare: (
AccountShare:{Id=00rE000002UB7YbIAL, UserOrGroupId=005E0000004JdrRIAS, AccountId=001E000000AXWYcIAP, RowCause=Owner},
AccountShare:{Id=00rE000000Q08DOIAZ, UserOrGroupId=00GE0000000YyFkMAK, AccountId=001E000000AXWYcIAP, RowCause=Rule},
AccountShare:{Id=00rE000001aalGeIAI, UserOrGroupId=00GE0000001axyCMAQ, AccountId=001E000000AXWYcIAP, RowCause=Rule},
AccountShare:{Id=00rE000002SRBAQIA5, UserOrGroupId=00GE0000001ceIRMAY, AccountId=001E000000AXWYcIAP, RowCause=Rule},
AccountShare:{Id=00rE000002SRimBIAT, UserOrGroupId=00GE0000001ceISMAY, AccountId=001E000000AXWYcIAP, RowCause=Rule},
AccountShare:{Id=00rE000002SSGOpIAP, UserOrGroupId=00GE0000001ceIUMAY, AccountId=001E000000AXWYcIAP, RowCause=Rule},
AccountShare:{Id=00rE000002SSQO2IAP, UserOrGroupId=00GE0000001ceUeMAI, AccountId=001E000000AXWYcIAP, RowCause=Rule},
AccountShare:{Id=00rE000002SSX9CIAX, UserOrGroupId=00GE0000001ceIIMAY, AccountId=001E000000AXWYcIAP, RowCause=Rule},
AccountShare:{Id=00rE000002VAP5GIAX, UserOrGroupId=00GE0000001cgn5MAA, AccountId=001E000000AXWYcIAP, RowCause=TerritoryManual}, AccountShare:{Id=00rE0000044k7wgIAA, UserOrGroupId=00GE0000001chdnMAA, AccountId=001E000000AXWYcIAP, RowCause=TerritoryManual}, ...)

|DEBUG|=== size of listOfAccountShare: 17

|DEBUG|=== all AccountShare keys (AccountID) in the map: {001E000000AXWYcIAP}
|DEBUG|=== all AccountShare values (UserorGroupID) in the map (as a List): (00GE00000026tBIMAY)
|DEBUG|=== size of mapOfAccountShare: 1

|DEBUG|=== contents of listOfGroup: (Group:{Id=00GE00000026tBIMAY, RelatedId=04TE0000000TcJfMAK})
|DEBUG|=== size of listOfGroup: 1
Vishal_GuptaVishal_Gupta
Hi,

In your below query AccountId is same for all 17 records and thats why Map is overwriting the AccountId and only creating one record in mapOfAccountShare. In Map Key is the unique value if we set duplicate in map, its autmatically overwrite the existing one.

List<AccountShare> listOfAccountShare =
    [Select Id, UserOrGroupId, AccountId, RowCause from AccountShare where AccountId IN :setOfAccountIds];

for(AccountShare acctShare : listOfAccountShare){
    mapOfAccountShare.put(acctShare.AccountId, acctShare.UserOrGroupId);  //AccountId is same for all records and thats why its overwriting.     }   

Please verify it and let me know if its help you out.

Thanks,
Vishal
SFDCDevQASFDCDevQA
So what should I do to map these (or list or set) so that in the end I can a list of all the territories associated with that one account?  The only way I see to do it is to go through the Account Share to the Group to the Territory but if the map immediately truncates down to just one of the groups from the Account Share then that won't work.  So would should I do to continue getting lists?

Thanks,
Amanda
Vishal_GuptaVishal_Gupta
Hi,

Please use below code, it will work for you.

trigger AccountTerritories on Account (before update){
    if(Trigger.isBefore){
        Set<Id> setOfAccountIds = new Set<Id>();

        for(Account acct : Trigger.New){
            if(Trigger.isUpdate){
                if(acct.Id != null){
                    setOfAccountIds.add(acct.Id);
                }
            }
        }
 
        if(setOfAccountIds.size() > 0){

        /* Declaration of collection data types */
Map<Id, Id> mapOfAccountShare = new Map<Id, Id>();
       Map<Id, Id> mapOfGroup = new Map<Id, Id>();
       Map<Id, Territory> mapOfUserTerritory = new Map<Id, Territory>();


//Query in Account Share object

    List<AccountShare> listOfAccountShare =
    [Select Id, UserOrGroupId, AccountId, RowCause from AccountShare where AccountId IN :setOfAccountIds];
    System.debug('=== contents of listOfAccountShare: ' + listOfAccountShare);

//Map of Account Share
    for(AccountShare acctShare : listOfAccountShare){
    mapOfAccountShare.put(acctShare.Id, acctShare.UserOrGroupId);        
    }      
    System.debug('=== all AccountShare keys in the map: ' + mapOfAccountShare.keySet());  
    System.debug('=== all AccountShare values in the map (as a List): ' + mapOfAccountShare.values());

    //Query in Group object            
    List<Group> listOfGroup = [Select Id, RelatedId from Group where Type='Territory' and Id IN :mapOfAccountShare.Values()];
    System.debug('=== contents of listOfGroup: ' + listOfGroup);
//Map of Group object
    for(Group groupRecord : listOfGroup){
    mapOfGroup.put(groupRecord.Id, groupRecord.RelatedId);        
    }
    System.debug('=== all Group keys in the map: ' + mapOfGroup.keySet());  
    System.debug('=== all Group values in the map (as a List): ' + mapOfGroup.values());

    //Query in Territory object
    Map<Id, Territory> mapOfTerritories =
    new Map<Id, Territory>([select id, name, ParentTerritoryId from Territory where Id IN:mapOfGroup.Values() ]);  
    System.debug('=== all Territories keys in the map: ' + mapOfTerritories.keySet());  
    System.debug('=== all Territories values in the map (as a List): ' + mapOfTerritories.values());  
}
}
}

Please let me know if I can help you more.

Thanks,
Vishal
This was selected as the best answer
SFDCDevQASFDCDevQA
That did work thank you.  Now with so many maps to get from Accounts to Territories how do I take the territory names that the map lists and put them in the correct account(s) that had an update?  This would be more complicated than just listing what the final map says correct?  Because if multiple accounts are updated won't the final map give the territories of all Accounts updated?

Thank you so much,
Amanda
SFDCDevQASFDCDevQA
I had to change it up a bit to circle back to the Account ID.  Below is how I now have it but circling back is still a bit of an issue.  How do I get the list of Territories specific to the Account updated or created and add it to the Account custom field (text area)?

trigger AccountTerritories on Account (before update){
    if(Trigger.isBefore){
        Set<Id> setOfAccountIds = new Set<Id>();

        for(Account acct : Trigger.New){
            if(Trigger.isUpdate){
                if(acct.Id != null){
                    setOfAccountIds.add(acct.Id);
                }
            }
        }
 
        if(setOfAccountIds.size() > 0){

        /* Declaration of collection data types */
        Map<id,List<AccountShare>> MapOfAccountShare = new    Map<id,List<AccountShare>>();
       Map<Id, Id> mapOfGroup = new Map<Id, Id>();
       Map<Id, String> mapOfTerritories = new Map<Id, String>();


//Query in Account Share object
    /*
    Those Accounts which are assigned via Territory Assignment Rules.
You can query those Accounts by filtering RowCause = 'Territory' in AccountShare object query.
    */
    List<AccountShare> listOfAccountShare =
    [Select Id, UserOrGroupId, AccountId, RowCause from AccountShare where AccountId IN :setOfAccountIds];
    System.debug('=== contents of listOfAccountShare: ' + listOfAccountShare);
    System.debug('=== size of listOfAccountShare: ' + listOfAccountShare.size());
    List<Id> Groupids = new List<Id>();
    for(AccountShare a :listofAccountShare){
    Groupids.add(a.UserOrGroupId);
    }

    //Map of Account Share

  for(AccountShare acctShare : listOfAccountShare ){
        if (MapOfAccountShare.containsKey(acctShare.AccountID))
            {
        MapOfAccountShare.get(acctShare.AccountID). add(acctShare);
        }
        else{
        MapOfAccountShare.put(acctShare.AccountID, new  List <AccountShare> { acctShare });
        }  
        }  
    System.debug('=== all AccountShare keys in the map: ' + mapOfAccountShare.keySet());  
    System.debug('=== all AccountShare values in the map (as a List): ' + mapOfAccountShare.values());
    System.debug('=== size of mapOfAccountShare: ' + mapOfAccountShare.size());

    //Query in Group object            
    List<Group> listOfGroup = [Select Id, RelatedId from Group where Type='Territory' and Id IN :GroupIDs];
    System.debug('=== contents of listOfGroup: ' + listOfGroup);
    System.debug('=== size of listOfGroup: ' + listOfGroup.size());
//Map of Group object
    for(Group groupRecord : listOfGroup){
    mapOfGroup.put(groupRecord.Id, groupRecord.RelatedId);        
    }
    System.debug('=== all Group keys in the map: ' + mapOfGroup.keySet());  
    System.debug('=== all Group values in the map (as a List): ' + mapOfGroup.values());
    System.debug('=== size of MapOfGroup: ' + mapOfGroup.size());

    //Query in Territory object
    List<Territory> listOfTerritory = [Select Id, Name from Territory where Id IN :mapOfGroup.Values()];
    System.debug('=== contents of listOfTerritories: ' + listOfTerritory);
    System.debug('=== size of listOfTerritories: ' + listOfTerritory.size());
    //Map of Territory object
    
    for(Territory Territories : listOfTerritory){
    mapOfTerritories.put(Territories.Id, Territories.Name);
    System.debug('=== all Territories keys in the map: ' + mapOfTerritories.keySet());  
    System.debug('=== all Territories values in the map (as a List): ' + mapOfTerritories.values());  
    System.debug('=== size of MapOfTerritories: ' + mapOfTerritories.size());
    }
    for (Account updatedAccount : Trigger.new) {
    User territory = MapofTerritories.get(mapofGroup.get(mapofAccountShare.get(updatedaccount.id )));
    updatedAccount.territories = territory.name;
    }
 
}

}
}
SFDCDevQASFDCDevQA
Finally figured out how to get it mapped properly. Here's what I have at the end to map back to the beginning and put in the Territory names.

for (Account updatedAccount : Trigger.new) {
            List<AccountShare> accountSharesList = mapofAccountShare.get(updatedaccount.id);
            
            // Start with empty string of territories
            String territories = '';
            for (AccountShare accountshare : accountshareslist){ //loop through accountShares
              // Get the group from the share
              id groupid = accountshare.userorgroupid;
              // Get the territory from the group map
              id territoryid  = mapofGroup.get(groupid);
              // Get the Territory Name from the territory Map
              string TerritoryName = MapofTerritories.get(territoryid);
              if(territoryname != null){
                   // Add next territory name to string of territories
                   territories = territories + territoryName +', ';// this is how i add the new territory to my string of territories
              }
            }
            // remove last two chars here, but only if territories is not empty string
            if(String.isNotBlank(territories)){
                String TerritoryNames = Territories.Substring(0,Territories.length()-2);
                updatedAccount.territories__c = TerritoryNames;
                }