+ Start a Discussion
Matt MetrosMatt Metros 

Error:Apex trigger AccountTrigger caused an unexpected exception, contact your administrator: AccountTrigger: execution of AfterUpdate caused by: System.DmlException: Update failed. First exception on row 0; INSUFFICIENT_ACCESS_ON_CROSS_REFERENCE_ENTITY

public with sharing class NumberOfAccountsRelatedToUser {

	public static void triggerHandler( System.TriggerOperation triggerEvent , list<Account> newAccounts, List<Account> oldAccounts) {

		Set<ID> related_user_IDs = new Set<ID>();

		if(triggerEvent == TriggerOperation.AFTER_INSERT){
			for(Account a: newAccounts){
				related_user_IDs.add(a.SDR_Owner__c);
				related_user_IDs.add(a.OwnerID);
			}
		}
		if(triggerEvent == TriggerOperation.AFTER_UPDATE){
			for(Account a: newAccounts){
				related_user_IDs.add(a.SDR_Owner__c);
				related_user_IDs.add(a.OwnerID);
			}
			for(Account a: oldAccounts){
				related_user_IDs.add(a.SDR_Owner__c);
				related_user_IDs.add(a.OwnerID);
			}
		}

		if(triggerEvent == TriggerOperation.AFTER_DELETE){
			for(Account a: oldAccounts){
				related_user_IDs.add(a.SDR_Owner__c);
				related_user_IDs.add(a.OwnerID);
			}
		}

		// now we want to say hey, we have these User ID's
		// lets go found how many accounts in which they are the SDR Owner and Account Owner


		List<AggregateResult> related_user_prospect_accounts = [SELECT COUNT(ID) sdr_owner_accounts, SDR_Owner__c FROM Account WHERE SDR_Owner__c in :related_user_IDs and (type ='Prospect - Being Worked' OR type='Prospect - Open' ) GROUP BY SDR_Owner__c];
		List<AggregateResult> related_user_owner_prospect_accounts = [SELECT COUNT(ID) owner_accounts, OwnerID FROM Account WHERE OwnerID in :related_user_IDs and (type ='Prospect - Being Worked' OR type='Prospect - Open' ) GROUP BY OwnerId];


		Map<Id, List<Integer>> userID_And_num_of_accounts = new Map<Id, List<Integer>>();

		// we are assuming there will always be an account owner
		// which is definitely a fine assertion, because an account cannot be created without an owner
		for(AggregateResult ar: related_user_owner_prospect_accounts){
		    ID owner_ID = (ID)ar.get('OwnerID');

		    // check if Id is in Map, only initialize new list if ID not in map
		    if(!userID_And_num_of_accounts.containsKey(owner_ID)){
		        userID_And_num_of_accounts.put(owner_ID, new List<Integer>());
		    }

		    userID_And_num_of_accounts.get(owner_ID).add((Integer)ar.get('owner_accounts'));
		
		}



		for(AggregateResult ar: related_user_prospect_accounts){
		    ID sdr_owner_ID = (ID)ar.get('SDR_Owner__c');

		    // check if Id is in Map, only initialize new list if ID not in map
		    if(!userID_And_num_of_accounts.containsKey(sdr_owner_ID)){
		        userID_And_num_of_accounts.put(sdr_owner_ID, new List<Integer>());
		    }

		    if(sdr_owner_ID == null){
		    	continue;
		    }
		    else{
		    	// add the number of sdr accounts to that IDs map
		    	userID_And_num_of_accounts.get(sdr_owner_ID).add((Integer)ar.get('sdr_owner_accounts'));
		    }

	
		}


		// now we want to update the users field
		List<ID> user_IDs = new List<ID>();

		for(ID user_ID: userID_And_num_of_accounts.keySet()){
			user_IDs.add(user_ID);
		}

		// now we want to get the actual user object
		List<User> users = [SELECT ID, SDR_Owner_Prospect__c , Account_Owner_Prospect__c FROM User WHERE ID in :user_IDs];


		List<User> users_to_update = new List<User>();
		for(User u: users){
			List<Integer> sdr_and_owner_accounts = userID_And_num_of_accounts.get(u.ID);			
			if(sdr_and_owner_accounts.size() == 1){
				u.Account_Owner_Prospect__c = sdr_and_owner_accounts[0];
				u.SDR_Owner_Prospect__c = 0;
			}
			else{
				u.Account_Owner_Prospect__c = sdr_and_owner_accounts[0];
				u.SDR_Owner_Prospect__c = sdr_and_owner_accounts[1];	
			}

			users_to_update.add(u);
		}

		update users_to_update;

	}


}

What is going on with this trigger. All I am trying to do is update two user fields when the trigger fires.
Best Answer chosen by Matt Metros
abhishek singh 497abhishek singh 497
Hello Matt,

Generally, the above error comes when there is some issue with access performance.
You can use the userRecordAccess object to check CRUD permissions
So pass the recordId and userId.. to check that user having what type of access on that record
you can check variables like HasDeleteAccess. If HasDeleteAccess true means user have delete access. If false then user don't have access

List<UserRecordAccess> lstUserRecordAccess = [SELECT RecordId,MaxAccessLevel,HasAllAccess, HasDeleteAccess, HasEditAccess, HasReadAccess, HasTransferAccess FROM UserRecordAccess WHERE UserId = '00550000000rlrX' AND RecordId = '0015000000TaWdI'];

Please try above and let me know it has solved your problem.
If yes, please mark it as the best answer.

Thanks & Regards,
Abhishek Singh.