1

I am trying to write a trigger on the contact object which updates a custom field on the account if the contact record was created or updated by the account owner or an account team member.

The trigger is shown below. It works fine when a single contact is created or updated, but it obviously will give incorrect results when inserting or updating multiple records via the Dataloader (because it indiscriminately dumps all AccountTeamMember UserIds into a set, and then checks the CreatedById and LastModifiedById values against the entire set -- so results that may be true for one account will end up being true for all accounts).

I have tried rewriting this with maps, but it got messy and I got confused -- I couldn't figure out how to check to see if the CreatedById or the LastModifiedId were contained in the map values (using a map like this:)

Map<Id, AccountTeamMember>

Any pointers would be much appreciated. Thanks!

trigger TriggerContactInactivity on Contact (after insert, after update) {

    Set<Id> accountId = new Set<Id>();
    Set<Id> accountOwnerId = new Set<Id>();
    Set<Id> teamMemberIds = new Set<Id>();

    for (Contact c: Trigger.new) {
        accountId.add(c.AccountId);
    }

    List<Account> a = [SELECT Id, OwnerId FROM Account WHERE id IN :accountId];
    for (Account account :a) {
        accountOwnerId.add(account.OwnerId);
    }

    List<AccountTeamMember> atm = [SELECT UserId FROM AccountTeamMember WHERE AccountId = :accountId];
    for (AccountTeamMember accountTeamMember :atm) {
        teamMemberIds.add(accountTeamMember.UserId);
    }

    Map<Id, Account> accountsToUpdate = new Map<Id, Account>();

    for (Contact c: Trigger.new) {
        for (Account acc : a) {
            if (Trigger.IsInsert && c.AccountId != NULL && (teamMemberIds.contains(c.CreatedById) || accountOwnerId.contains(c.CreatedById))) {
                acc.InactivityDate__c = date.today();
                accountsToUpdate.put(acc.Id, acc);
            }

            if (Trigger.IsUpdate && c.AccountId != NULL && (teamMemberIds.contains(c.LastModifiedById) || accountOwnerId.contains(c.LastModifiedById))) {
                acc.InactivityDate__c = date.today();
                accountsToUpdate.put(acc.Id, acc);
            }
        }
    }

    update accountsToUpdate.values();
}
0

1 Answer 1

3

Some small changes.

  1. You needed a Map of Account ID to team member IDs so I created that.
  2. No need for the second query for loop. Just use the subquery when querying for accounts

    trigger TriggerContactInactivity on Contact (after insert, after update) {
    
    Set<Id> accountId = new Set<Id>();
    Set<Id> accountOwnerId = new Set<Id>();
    Map<ID,Set<ID>> aTeams = New Map<ID,Set<ID>>();
    
    for (Contact c: Trigger.new) {
        accountId.add(c.AccountId);
    }
    
    List<Account> a = [SELECT Id, OwnerId, (SELECT UserId FROM AccountTeamMembers) FROM Account WHERE id IN :accountId];
    for (Account acc :a) {
        accountOwnerId.add(acc.OwnerId);
        aTeams.put(acc.id,New Set<ID>());
        for(AccountTeamMember team : acc.AccountTeamMembers){
            aTeam.get(acc.id).add(team.UserId);
        }
    }
    
    
    Map<Id, Account> accountsToUpdate = new Map<Id, Account>();
    
    for (Contact c: Trigger.new) {
        for (Account acc : a) {
            if (Trigger.IsInsert && c.AccountId != NULL && (ateam.get(acc.id).contains(c.CreatedById) || accountOwnerId.contains(c.CreatedById))) {
                acc.InactivityDate__c = date.today();
                accountsToUpdate.put(acc.Id, acc);
            }
    
            if (Trigger.IsUpdate && c.AccountId != NULL && (aTeam.get(acc.id).contains(c.LastModifiedById) || accountOwnerId.contains(c.LastModifiedById))) {
                acc.InactivityDate__c = date.today();
                accountsToUpdate.put(acc.Id, acc);
            }
        }
    }
    
    update accountsToUpdate.values();
    }
    
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .