[SalesForce] Error: System.LimitException: Too many future calls: 11

I am very new to Apex and I am having an issue with a trigger.

A little background:
I have 16 Lookup fields on the Account object that represent our Account Team Roles. I have a trigger that when a value is added to one of these fields it will create an Account Team Role and Account Share record.

I was able to successfully create the first bit of code to add update when one of the fields was used, but could not figure out how to add the other 15 to the same class. So I ended up creating 16 triggers and 16 Helper Classes. I know there is a better way to go about this but I couldn't figure it out. Now, after adding all 16 lines to my test class I am receiving the above error.

Below is one of the Triggers, one of the Helper Classes, the Future Call and my test class. Any help would be greatly appreciated.

Trigger:

trigger UpdateUKRepTeam on Account (After update, After insert){

    UpdateUKRepHelper.updateTeamMember(trigger.new, trigger.old);
}

Helper Class:

public class UpdateUKRepHelper{

    public static void updateTeamMember(List<Account> accounts, list<account> Accountsold){

        List<AccountShare> ashareLIST = new List<AccountShare>();
        List<AccountTeamMember> ATM = new List<AccountTeamMember>();
        List<AccountTeamMember> RemATM = new List<AccountTeamMember>();
        List<Account> acct = Trigger.new;
        integer i = 0;
        List<AccountTeamMember > ATMDeleteList = new List<AccountTeamMember >();
        List<AccountTeamMember >  ATMDelete = [select id, AccountId, UserId from AccountTeamMember where TeamMemberRole = 'UK Rep' and accountid in :accounts ]; 

        if (trigger.isUpdate)
        {
        for(Account a:accounts){
            for(Account old : Accountsold)
            {
                if (old.id == a.id)
                {
                AccountShare caSharingRule = new AccountShare();
                caSharingRule.AccountId = a.Id;
                caSharingRule.OpportunityAccessLevel = 'Edit';
                caSharingRule.CaseAccessLevel = 'Edit';
                caSharingRule.AccountAccessLevel = 'Edit';
                caSharingRule.UserOrGroupId = a.UK_Rep__c;
                ashareLIST.add(caSharingRule);

                   if(a.UK_Rep__c != null){

                        if(a.UK_Rep__c != null && old.UK_Rep__c == null){

                        AccountTeamMember Teammemberad=new AccountTeamMember();
                        Teammemberad.AccountId=a.id;
                        Teammemberad.UserId=a.UK_Rep__c;
                        Teammemberad.TeamMemberRole = 'UK Rep';
                        ATM.add(Teammemberad);
                        }
                        else if (old.UK_Rep__c != null)
                        {
                            for (AccountTeamMember Team : ATMDelete )
                            {
                                if(a.id == Team.AccountId)
                                {
                                    if (team.UserId != a.UK_Rep__c)
                                    {
                                    ATMDeleteList.add(team);
                                    }
                                }
                            }
                            AccountTeamMember Teammemberad=new AccountTeamMember();
                            Teammemberad.AccountId=a.id;
                            Teammemberad.UserId=a.UK_Rep__c;
                            Teammemberad.TeamMemberRole = 'UK Rep';
                            ATM.add(Teammemberad);
                        }    
                    }
                    else if (a.UK_Rep__c == null)
                    {
                        for (AccountTeamMember Team : ATMDelete )
                        {
                            if(a.id == Team.AccountId)
                            {
                                ATMDeleteList.add(team);
                            }
                        }                     
                    }
                }
            }
        }
        }
        else if (trigger.isInsert)
        for(Account a:accounts){

           AccountShare caSharingRule = new AccountShare();
           caSharingRule.AccountId = a.Id;
           caSharingRule.OpportunityAccessLevel = 'Edit';
           caSharingRule.CaseAccessLevel = 'Edit';
           caSharingRule.AccountAccessLevel = 'Edit';
           caSharingRule.UserOrGroupId = a.UK_Rep__c;
           ashareLIST.add(caSharingRule);

              if(a.UK_Rep__c != null){

                        if(a.UK_Rep__c != null ){

                        AccountTeamMember Teammemberad=new AccountTeamMember();
                        Teammemberad.AccountId=a.id;
                        Teammemberad.UserId=a.UK_Rep__c;
                        Teammemberad.TeamMemberRole = 'UK Rep';
                        ATM.add(Teammemberad);
                        }    
                    }
                    else if (a.UK_Rep__c == null)
                    {
                        for (AccountTeamMember Team : ATMDelete )
                        {
                            if(a.id == Team.AccountId)
                            {
                                ATMDeleteList.add(team);
                            }
                        }                       
                    }
        }       
        if(ATMDeleteList.size() > 0 )
        {
           Delete ATMDeleteList;
        }
         if(!ATM.isEmpty()){
                        insert ATM;  
                        UpdateBRHelper_future upfur = new UpdateBRHelper_future();
                        upfur.AccShare1(ashareList);         
                        //insert ashareList;
                        }
    }
}

Helper_future Class:

public class UpdateBRHelper_future{

    map<id, id> AccShareBacnkRep2 = new map<id, id>();
    public void AccShare1(list<AccountShare > asa)
    {

        for (AccountShare  as1 : asa)
        {
            AccShareBacnkRep2.put(as1.accountid, as1.UserOrGroupId );
        }
       AccShare(AccShareBacnkRep2  );
    }

    @future
    public static void AccShare(map<id, id> AccountSh)
    {
    List<AccountShare> ashareLIST = new List<AccountShare>();
        for(id i : AccountSh.keyset())
        {
                 AccountShare caSharingRule = new AccountShare();
                caSharingRule.AccountId = i;
                caSharingRule.OpportunityAccessLevel = 'Edit';
                caSharingRule.CaseAccessLevel = 'Edit';
                caSharingRule.AccountAccessLevel = 'Edit';
                caSharingRule.UserOrGroupId = AccountSh.get(i);  
                ashareLIST.add(caSharingRule);
          }   
        if(!Test.isRunningTest()){insert ashareLIST;}
    }
}

Test Class:

@isTest
public class UpdateBRHelperTest {    
    public static testMethod void insertNewAccount() {

    Profile p = [SELECT id from Profile where Name = 'US Sales - Consumer Compliance Rep'];

    User u = new User(alias = 'testu', email='test.user@testorg.com', emailencodingkey='UTF-8', lastname='User', languagelocalekey='en_US', localesidkey='en_US', profileid = p.Id,
        timezonesidkey='America/Los_Angeles', username='a.user@testorg.com');

    User u2 = new User(alias = 'testeru', email='tester.user@testorg.com', emailencodingkey='UTF-8', lastname='User', languagelocalekey='en_US', localesidkey='en_US', profileid = p.Id,
        timezonesidkey='America/Los_Angeles', username='b.user@testorg.com');

    User u3 = new User(alias = 'testing', email='testing.user@testorg.com', emailencodingkey='UTF-8', lastname='User', languagelocalekey='en_US', localesidkey='en_US', profileid = p.Id,
        timezonesidkey='America/Los_Angeles', username='c.user@testorg.com');

    User u4 = new User(alias = 'tested', email='tested.user@testorg.com', emailencodingkey='UTF-8', lastname='User', languagelocalekey='en_US', localesidkey='en_US', profileid = p.Id,
        timezonesidkey='America/Los_Angeles', username='d.user@testorg.com');

    User u5 = new User(alias = 'testme', email='test.user@testorg.com', emailencodingkey='UTF-8', lastname='User', languagelocalekey='en_US', localesidkey='en_US', profileid = p.Id,
        timezonesidkey='America/Los_Angeles', username='e.user@testorg.com');

    User u6 = new User(alias = 'testyou', email='test.user@testorg.com', emailencodingkey='UTF-8', lastname='User', languagelocalekey='en_US', localesidkey='en_US', profileid = p.Id,
        timezonesidkey='America/Los_Angeles', username='f.user@testorg.com');

    User u7 = new User(alias = 'testit', email='test.user@testorg.com', emailencodingkey='UTF-8', lastname='User', languagelocalekey='en_US', localesidkey='en_US', profileid = p.Id,
        timezonesidkey='America/Los_Angeles', username='g.user@testorg.com');

    User u8 = new User(alias = 'testhim', email='test.user@testorg.com', emailencodingkey='UTF-8', lastname='User', languagelocalekey='en_US', localesidkey='en_US', profileid = p.Id,
        timezonesidkey='America/Los_Angeles', username='h.user@testorg.com');

    User u9 = new User(alias = 'testher', email='test.user@testorg.com', emailencodingkey='UTF-8', lastname='User', languagelocalekey='en_US', localesidkey='en_US', profileid = p.Id,
        timezonesidkey='America/Los_Angeles', username='i.user@testorg.com');

    User u10 = new User(alias = 'testmine', email='test.user@testorg.com', emailencodingkey='UTF-8', lastname='User', languagelocalekey='en_US', localesidkey='en_US', profileid = p.Id,
        timezonesidkey='America/Los_Angeles', username='j.user@testorg.com');

    User u11 = new User(alias = 'testyour', email='test.user@testorg.com', emailencodingkey='UTF-8', lastname='User', languagelocalekey='en_US', localesidkey='en_US', profileid = p.Id,
        timezonesidkey='America/Los_Angeles', username='k.user@testorg.com');

    User u12 = new User(alias = 'testthem', email='test.user@testorg.com', emailencodingkey='UTF-8', lastname='User', languagelocalekey='en_US', localesidkey='en_US', profileid = p.Id,
        timezonesidkey='America/Los_Angeles', username='l.user@testorg.com');

    User u13 = new User(alias = 'testit', email='test.user@testorg.com', emailencodingkey='UTF-8', lastname='User', languagelocalekey='en_US', localesidkey='en_US', profileid = p.Id,
        timezonesidkey='America/Los_Angeles', username='m.user@testorg.com');

    User u14 = new User(alias = 'testours', email='test.user@testorg.com', emailencodingkey='UTF-8', lastname='User', languagelocalekey='en_US', localesidkey='en_US', profileid = p.Id,
        timezonesidkey='America/Los_Angeles', username='n.user@testorg.com');

    User u15 = new User(alias = 'testthat', email='test.user@testorg.com', emailencodingkey='UTF-8', lastname='User', languagelocalekey='en_US', localesidkey='en_US', profileid = p.Id,
        timezonesidkey='America/Los_Angeles', username='o.user@testorg.com');

    insert u; insert u2; insert u3; insert u4; insert u5; insert u6; insert u7; insert u8;
    insert u9; insert u10; insert u11; insert u12; insert u13; insert u14; insert u15;

    string uId = u.Id; string u2Id = u2.Id; string u3Id = u3.Id; string u4Id = u4.Id; string u5Id = u5.Id;
    string u6Id = u6.Id; string u7Id = u7.Id; string u8Id = u8.Id; string u9Id = u9.Id; string u10Id = u10.Id;
    string u11Id = u11.Id; string u12Id = u12.Id; string u13Id = u13.Id; string u14Id = u14.Id; string u15Id = u15.Id;

    Account a = new Account();
    a.OwnerId = u.Id;
    a.Name = 'Test Account';
    a.Banking_Rep__c  = u.Id;
    a.Brokerage_Rep__c = u2.Id;
    a.Examiner_Rep__c = u3.Id;
    a.Corp_Action_Rep__c = u4.Id;
    a.FundTax_Rep__c = u5.Id;
    a.ARC_Rep__c = u6.Id;
    a.BUS_Development_Rep__c = u7.Id;
    a.CAP_Retention_Rep__c = u8.Id;
    a.Examiner_Support__c = u9.Id;
    a.FRS__c = u10.Id;
    a.GK_Support__c = u11.Id;
    a.Insurance_Account_Executive__c = u12.Id;
    a.Insurance_Rep__c = u13.Id;
    a.Insurance_Support_Rep__c = u14.Id;
    a.UK_Rep__c = u15.Id;

    insert a;
    string aId = a.Id;

    AccountTeamMember atm = new AccountTeamMember();
    atm.AccountId=a.Id;
    atm.UserId=a.Banking_Rep__c;
    atm.TeamMemberRole = 'Banking Rep';    
    AccountTeamMember atm2 = new AccountTeamMember();
    atm2.AccountId=a.Id;
    atm2.UserId=a.Brokerage_Rep__c;
    atm2.TeamMemberRole = 'Brokerage Rep';    
    AccountTeamMember atm3 = new AccountTeamMember();
    atm3.AccountId=a.Id;
    atm3.UserId=a.Examiner_Rep__c;
    atm3.TeamMemberRole = 'Examiner Rep';  
    AccountTeamMember atm4 = new AccountTeamMember();
    atm4.AccountId=a.Id;
    atm4.UserId=a.Corp_Action_Rep__c;
    atm4.TeamMemberRole = 'Corp Action Rep';
    AccountTeamMember atm5 = new AccountTeamMember();
    atm5.AccountId=a.Id;
    atm5.UserId=a.FundTax_Rep__c;
    atm5.TeamMemberRole = 'FundTax Rep';
    AccountTeamMember atm6 = new AccountTeamMember();
    atm6.AccountId=a.Id;
    atm6.UserId=a.ARC_Rep__c;
    atm6.TeamMemberRole = 'ARC Rep';
    AccountTeamMember atm7 = new AccountTeamMember();
    atm7.AccountId=a.Id;
    atm7.UserId=a.BUS_Development_Rep__c;
    atm7.TeamMemberRole = 'BUS Development Rep';
    AccountTeamMember atm8 = new AccountTeamMember();
    atm8.AccountId=a.Id;
    atm8.UserId=a.CAP_Retention_Rep__c;
    atm8.TeamMemberRole = 'CAP Retention Rep';
    AccountTeamMember atm9 = new AccountTeamMember();
    atm9.AccountId=a.Id;
    atm9.UserId=a.Examiner_Support__c;
    atm9.TeamMemberRole = 'Examiner Support';
    AccountTeamMember atm10 = new AccountTeamMember();
    atm10.AccountId=a.Id;
    atm10.UserId=a.FRS__c;
    atm10.TeamMemberRole = 'FRS';
    AccountTeamMember atm11 = new AccountTeamMember();
    atm11.AccountId=a.Id;
    atm11.UserId=a.GK_Support__c;
    atm11.TeamMemberRole = 'GK Support';
    AccountTeamMember atm12 = new AccountTeamMember();
    atm12.AccountId=a.Id;
    atm12.UserId=a.Insurance_Account_Executive__c;
    atm12.TeamMemberRole = 'Insurance Account Executive';
    AccountTeamMember atm13 = new AccountTeamMember();
    atm13.AccountId=a.Id;
    atm13.UserId=a.Insurance_Rep__c;
    atm13.TeamMemberRole = 'Insurance Rep';
    AccountTeamMember atm14 = new AccountTeamMember();
    atm14.AccountId=a.Id;
    atm14.UserId=a.Insurance_Support_Rep__c;
    atm14.TeamMemberRole = 'Insurance Support Rep';
    AccountTeamMember atm15 = new AccountTeamMember();
    atm15.AccountId=a.Id;
    atm15.UserId=a.UK_Rep__c;
    atm15.TeamMemberRole = 'UK Rep';
        insert atm; insert atm2; insert atm3; insert atm4; insert atm5; 
        insert atm6; insert atm7; insert atm8; insert atm9; insert atm10; 
        insert atm11; insert atm12; insert atm13; insert atm14; insert atm15;

    AccountShare ashare = new AccountShare();
    ashare.AccountId = a.Id;
    ashare.OpportunityAccessLevel = 'Edit';
    ashare.CaseAccessLevel = 'Edit';
    ashare.AccountAccessLevel = 'Edit';
    ashare.UserOrGroupId = a.Banking_Rep__c;
    ashare.UserOrGroupId = a.Brokerage_Rep__c;
    ashare.UserOrGroupId = a.Examiner_Rep__c;
    ashare.UserOrGroupId = a.Corp_Action_Rep__c;
    ashare.UserOrGroupId = a.FundTax_Rep__c;
    ashare.UserOrGroupId = a.ARC_Rep__c;
    ashare.UserOrGroupId = a.BUS_Development_Rep__c;
    ashare.UserOrGroupId = a.CAP_Retention_Rep__c;
    ashare.UserOrGroupId = a.Examiner_Support__c;
    ashare.UserOrGroupId = a.FRS__c;
    ashare.UserOrGroupId = a.GK_Support__c;
    ashare.UserOrGroupId = a.Insurance_Account_Executive__c;
    ashare.UserOrGroupId = a.Insurance_Rep__c;
    ashare.UserOrGroupId = a.Insurance_Support_Rep__c;
    ashare.UserOrGroupId = a.UK_Rep__c;

    Account acct = [SELECT OwnerId, Name, Banking_Rep__c, Brokerage_Rep__c, Examiner_Rep__c, Corp_Action_Rep__c, FundTax_Rep__c, ARC_Rep__c, BUS_Development_Rep__c, 
        CAP_Retention_Rep__c, Examiner_Support__c, FRS__c, GK_Support__c, Insurance_Account_Executive__c, Insurance_Rep__c, Insurance_Support_Rep__c, UK_Rep__c  FROM Account WHERE Id =:a.Id];

    acct.Banking_Rep__c = u.Id;
    acct.Brokerage_Rep__c = u2.Id;
    acct.Examiner_Rep__c = u3.Id;
    acct.Corp_Action_Rep__c = u4.Id;
    acct.FundTax_Rep__c = u5.Id;
    acct.ARC_Rep__c = u6.Id;
    acct.BUS_Development_Rep__c = u7.Id;
    acct.CAP_Retention_Rep__c = u8.Id;
    acct.Examiner_Support__c = u9.Id;
    acct.FRS__c = u10.Id;
    acct.GK_Support__c = u11.Id;
    acct.Insurance_Account_Executive__c = u12.Id;
    acct.Insurance_Rep__c = u13.Id;
    acct.Insurance_Support_Rep__c = u14.Id;
    acct.UK_Rep__c = u15.Id;
    update a;

    AccountShare acctshare = [SELECT UserorGroupId, AccountId, OpportunityAccessLevel, ContactAccessLevel, CaseAccessLevel, AccountAccessLevel FROM AccountShare WHERE AccountId =: a.Id];
    }       
}

Best Answer

If you want to execute the same logic for 16 different fields then obviously it would be best to write the algorithm once. And in Salesforce bulking up any database reads and writes is important too. So one trigger that deals with multiple Accounts and handles all 16 fields would be ideal. Restructuring your code now is likely to avoid a lot of future pain.

To execute Apex logic in such a trigger, the get and put methods that take the field name string can be used:

List<Xyz__c> updates = new List<Xyz__c>();
Set<String> fields = new Set<String>{'UK_Rep__c', 'FR_Rep__c'', ...};
for (Account a : Trigger.new) {
    // Repeat algorithm for each of the 16 fields
    for (String field : fields) {
        Id repId = (Id) a.get(field);
        ...
    }
}
update updates;

And where you need the query to vary a lot, the query can be created as a string and executed as Dynamic SOQL. (Or sometimes just a where abc in :set may suffice.)

Also note that the sort of code shown immediately below is generally lethal (= governor limit exception). Fine with 10 Accounts where on average 10x10/2=50 times round the inner loop, but with 1,000 accounts its 1,000x1,000/2=500,000.

for(Account a:accounts){
    for(Account old : Accountsold)
    {
        if (old.id == a.id)
        {

Pass Trigger.oldMap into the class to remove the exponential factor:

for(Account a : accounts) {
    Account old : oldAccountsMap.get(a.Id);

Having read through your question and comments I still don't understand why @future is being used. What goes wrong if it is removed?

@Kevin C - The only way StackExchange is allowing me to reply is by editing your Answer. Again I apologize for not using the site as intended and will visit the help center when I have a moment.

First, thank you for your helpful response. To answer your question, the following scenario will occur if @future is removed. -If John D is the Account Owner and I attempt to add him to one of the Team Role fields on the Account then I receive an error. I do not have the exact error handy, but it is basically saying that I cannot perform the function because I am attempting to give John D lower permissions then what he already has. Due to him being the Account Owner he has 'Full'Access, but my code is trying to give him 'Read/Write'. I would be fine with 'Full Access' but the value is not available in Apex. @future allows the Account Owner to be added as a Team Member when adding him to the custom fields. Again, thank you for your response. Like I mentioned, I am VERY green when it comes to APEX and really trying to get a handle on it. I will take a closer look at what you provided and see if I can piece it all together.