2

Scenario

I have Community users that I need to share some account records to, where the Account that the Community user is linked to is referenced by a lookup field on the Account record to share.I have created a trigger and handler class on account to create a sharing record for each individual Community user.

This is using Customer Community Plus licences so Apex sharing is permitted, OWD for External users on Account is set to Private and the Manual Sharing option is enabled. All the Accounts and other records I need to share are owned by an integration account as master data fed from another system.

If I manually create 1 record linked to a 'Retailer' Account with 1 community user setup it will happily run the trigger and create the sharing record, but if I try it on 'Retailer' account with 2 or more community users it throws the error:

15:29:32:044 FATAL_ERROR System.ListException: Before Insert or Upsert list must not have two identically equal elements

Trigger code

    trigger WSC_Account_Trigger on Account (before insert, after insert, before update, after update) {

   if (RecursiveTriggerHandler.isFirstTime) {
     RecursiveTriggerHandler.isFirstTime = false;
    If(Trigger.isbefore&&trigger.isInsert){
        WSC_Account_Trigger_Methods.accountShareNew(Trigger.New);
        //call helper class to set Apex account sharing
        //
    }

    If(trigger.isbefore&&Trigger.isUpdate){
         WSC_Account_Trigger_Methods.accountShareUpdate(Trigger.New, Trigger.Old);
       //call helper class to set Apex account sharing 

    }
   } //end of recursive handler
}

Trigger Handler class

public class WSC_Account_Trigger_Methods {

    Public static void accountShareNew(List<Account> shareAccounts){
        if(shareAccounts!=Null&&shareAccounts.size()>0) {
        List<AccountShare> toShareAccount = new List<AccountShare>();
        AccountShare shAccounts = new AccountShare();
        for(Account newAcc : shareAccounts){
            //Water retailer shares
            system.Debug('premises name '+newAcc.Name);
            if(newAcc.Retailer__c!=Null){
                Id waterRetailerId = newAcc.Retailer__c;
                Id PremisesId = newAcc.Id;
                List<User> accUsers = new List<User>();
                System.debug('Water Retailer Id '+waterRetailerId);
                accUsers = [SELECT Id FROM user WHERE User.AccountId = :waterRetailerId];
                System.debug('accUsers '+ accUsers.size());
                for(User shareUser : accUsers){
                     System.debug('Premises name '+ newAcc.Name+' '+PremisesId+' '+shareUser.Id);
                     shAccounts.AccountId = PremisesId;
                     shAccounts.UserOrGroupId = shareUser.Id;
                     shAccounts.AccountAccessLevel = 'Read';
                    // shAccounts.CaseAccessLevel='Read';
                    // shAccounts.ContactAccessLevel='None';
                    // shAccounts.OpportunityAccessLevel='None';
                     toShareAccount.add(shAccounts);
                }
            }
        } //end water retailer shares

       for(Account newAcc : shareAccounts){
            //Sewerage retailer shares
            if(newAcc.Sewerage_Retailer__c!=Null&&newAcc.Retailer__c!=newAcc.Sewerage_Retailer__c){
                Id sewerageRetailerId = newAcc.Sewerage_Retailer__c;
                Id waterRetailerId = newAcc.Retailer__c;
                List<User> accUsers_s = new List<User>();
                accUsers_s = [SELECT Id FROM user 
                              WHERE User.AccountId= :sewerageRetailerId AND User.AccountId!= :waterRetailerId];
                System.debug('accUsers_s '+ accUsers_s.size());
                for(User shareUser : accUsers_s){
                     shAccounts.AccountId = newAcc.Id;
                     shAccounts.UserOrGroupId = shareUser.Id;
                     shAccounts.AccountAccessLevel = 'Read';
                  //   shAccounts.CaseAccessLevel='Read';
                     shAccounts.ContactAccessLevel='None';
                     shAccounts.OpportunityAccessLevel='None';
                     toShareAccount.add(shAccounts);
                }
            }
        } //end sewerage retailer shares 
        System.debug('No of shares to create'+toShareAccount.size());
        System.assert(toShareAccount.size()>0);
        Database.SaveResult[] result = Database.insert(toShareAccount, false);
    }  
   }

    public static void accountShareUpdate(List<Account> shareAccounts, List<Account> oldAccounts){
        System.debug('No of accounts '+shareAccounts.size());
        if(shareAccounts!=Null&&shareAccounts.size()>0) {
            //compare old and new values for Retailer and Sewerage Retailer
            //
            List<AccountShare> toShareAccount = new List<AccountShare>();
            AccountShare shAccounts = new AccountShare();

            Map<Id, Account> mapOldAccounts = new Map<Id, Account>(); 
            for(Account oldAccs :oldAccounts) {
                mapOldAccounts.put(OldAccs.Id,OldAccs);
            }
            for(Account changedAccs :shareAccounts){
                Id PremisesId = changedAccs.Id;
                Id waterRetailerId = changedAccs.Retailer__c;

                if(changedAccs.Retailer__c != mapoldAccounts.get(changedAccs.Id).Retailer__c
                   &&changedAccs.Retailer__c!=Null){
                      List<User> accUsers = new List<User>();
                      System.debug('Water Retailer Id '+waterRetailerId);
                      accUsers = [SELECT Id FROM user WHERE User.AccountId = :waterRetailerId];
                      System.debug('accUsers '+ accUsers.size());
                      for(User shareUser : accUsers){
                         System.debug('Premises name '+ changedAccs.Name+' '+PremisesId+' '+shareUser.Id);
                         shAccounts.AccountId = PremisesId;
                         shAccounts.UserOrGroupId = shareUser.Id;
                         shAccounts.AccountAccessLevel = 'Read';
                       // shAccounts.CaseAccessLevel='Read';
                         shAccounts.ContactAccessLevel='None';
                         shAccounts.OpportunityAccessLevel='None';
                         toShareAccount.add(shAccounts);
                      }
                }
                //
            }
            if(toShareAccount.size()>0){
            System.debug('No of shares to create'+toShareAccount.size());
            System.assert(toShareAccount.size()>0);
            Database.SaveResult[] result = Database.insert(toShareAccount, false);
            }
        }

    }

}
  • I am starting to wonder if I should re-architect this to use groups as that would simplify the sharing options. – Dave Humm Jan 24 '17 at 16:50
  • When I've gone down this rabbit hole I found complex map keys (IdPair) quite useful. – Adrian Larson Jan 24 '17 at 16:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.