You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apex类添加After Update实现联系人数量汇总字段更新

问题描述

我写了以下Apex类和触发器,用于在Contact添加或移除关联Account时,更新Account层级的Number_of_Contacts__c字段,目的是在Account报表中展示每个Account关联的Contact数量。由于Salesforce不支持Account到Contact的汇总字段,且Flow只能处理Contact创建或删除场景,所以用Apex实现。现有代码能处理AFTER_INSERT、AFTER_DELETE、AFTER_UNDELETE操作,但不知道怎么添加AFTER_UPDATE触发器逻辑,实现Contact更换关联Account时更新Number_of_Contacts__c字段,之前尝试没成功。

现有代码

ContactTriggerHandler类

public without sharing class ContactTriggerHandler {
    
    private Set<Id> getAccountIds(List<Contact> contacts) {
        Set<Id> accountIds = new Set<Id>();
        for(Contact c : contacts) {
            if(c.AccountId != null) {
                accountIds.add(c.AccountId);
            }
        }
        return accountIds;
    }
    
    private Map<Id, Account> getAccountMap(Set<Id> accountIds) {
        return new Map<Id, Account>([SELECT Id, Number_of_Contacts__c FROM Account WHERE Id in :accountIds]);
    }
    
    public void process(List<Contact> contacts, System.TriggerOperation operation) {
        Set<Id> accountIds = getAccountIds(contacts);
        if(accountIds.size() > 0) {
            Map<Id, Account> accountMap = getAccountMap(accountIds);
            for(Contact c : contacts) {
                if(accountMap.containsKey(c.AccountId)) {
                    switch on operation{
                        when AFTER_INSERT {
                            accountMap.get(c.AccountId).Number_of_Contacts__c += 1;
                        }
                        when AFTER_DELETE {
                            accountMap.get(c.AccountId).Number_of_Contacts__c -= 1;
                        }
                        when AFTER_UNDELETE {
                            accountMap.get(c.AccountId).Number_of_Contacts__c += 1;
                        }
                    }
                }
            }
            update accountMap.values();
        }
    }
}

ContactTrigger触发器

trigger ContactTrigger on Contact (after insert, after delete, after undelete) {
    ContactTriggerHandler handler = new ContactTriggerHandler();
    switch on Trigger.operationType {
        when AFTER_INSERT {
            handler.process(Trigger.new, Trigger.operationType);
        }
        when AFTER_DELETE {
            handler.process(Trigger.old, Trigger.operationType);
        }
        when AFTER_UNDELETE {
            handler.process(Trigger.new, Trigger.operationType);
        }
    }
}
解决方案

要处理Contact更换Account的场景,需要同时操作旧关联Account和新关联Account:旧Account的联系人数减1,新Account的联系人数加1。具体修改如下:

1. 修改触发器,添加after update触发事件

trigger ContactTrigger on Contact (after insert, after delete, after undelete, after update) {
    ContactTriggerHandler handler = new ContactTriggerHandler();
    switch on Trigger.operationType {
        when AFTER_INSERT {
            handler.process(Trigger.new, Trigger.operationType);
        }
        when AFTER_DELETE {
            handler.process(Trigger.old, Trigger.operationType);
        }
        when AFTER_UNDELETE {
            handler.process(Trigger.new, Trigger.operationType);
        }
        when AFTER_UPDATE {
            // 传递新旧记录集合给新增的处理方法
            handler.processUpdate(Trigger.new, Trigger.oldMap);
        }
    }
}

2. 在Handler类中新增processUpdate方法,并调整辅助逻辑

public without sharing class ContactTriggerHandler {
    
    private Set<Id> getAccountIds(List<Contact> contacts) {
        Set<Id> accountIds = new Set<Id>();
        for(Contact c : contacts) {
            if(c.AccountId != null) {
                accountIds.add(c.AccountId);
            }
        }
        return accountIds;
    }
    
    // 新增方法:收集所有需要更新的新旧AccountId
    private Set<Id> getOldAndNewAccountIds(List<Contact> newContacts, Map<Id, Contact> oldContactMap) {
        Set<Id> accountIds = new Set<Id>();
        for(Contact newC : newContacts) {
            Contact oldC = oldContactMap.get(newC.Id);
            // 添加旧AccountId(如果存在)
            if(oldC.AccountId != null) {
                accountIds.add(oldC.AccountId);
            }
            // 添加新AccountId(如果存在)
            if(newC.AccountId != null) {
                accountIds.add(newC.AccountId);
            }
        }
        return accountIds;
    }
    
    private Map<Id, Account> getAccountMap(Set<Id> accountIds) {
        return new Map<Id, Account>([SELECT Id, Number_of_Contacts__c FROM Account WHERE Id in :accountIds]);
    }
    
    public void process(List<Contact> contacts, System.TriggerOperation operation) {
        Set<Id> accountIds = getAccountIds(contacts);
        if(accountIds.size() > 0) {
            Map<Id, Account> accountMap = getAccountMap(accountIds);
            for(Contact c : contacts) {
                if(accountMap.containsKey(c.AccountId)) {
                    switch on operation{
                        when AFTER_INSERT {
                            accountMap.get(c.AccountId).Number_of_Contacts__c += 1;
                        }
                        when AFTER_DELETE {
                            accountMap.get(c.AccountId).Number_of_Contacts__c -= 1;
                        }
                        when AFTER_UNDELETE {
                            accountMap.get(c.AccountId).Number_of_Contacts__c += 1;
                        }
                    }
                }
            }
            update accountMap.values();
        }
    }
    
    // 新增处理Contact更新的方法
    public void processUpdate(List<Contact> newContacts, Map<Id, Contact> oldContactMap) {
        Set<Id> accountIds = getOldAndNewAccountIds(newContacts, oldContactMap);
        if(accountIds.size() == 0) return;
        
        Map<Id, Account> accountMap = getAccountMap(accountIds);
        
        for(Contact newC : newContacts) {
            Contact oldC = oldContactMap.get(newC.Id);
            Id oldAccountId = oldC.AccountId;
            Id newAccountId = newC.AccountId;
            
            // 仅当AccountId发生变化时执行计数调整
            if(oldAccountId != newAccountId) {
                // 旧Account联系人数减1(如果存在)
                if(oldAccountId != null && accountMap.containsKey(oldAccountId)) {
                    accountMap.get(oldAccountId).Number_of_Contacts__c -= 1;
                }
                // 新Account联系人数加1(如果存在)
                if(newAccountId != null && accountMap.containsKey(newAccountId)) {
                    accountMap.get(newAccountId).Number_of_Contacts__c += 1;
                }
            }
        }
        
        update accountMap.values();
    }
}

关键说明

  • 新增getOldAndNewAccountIds方法,确保不会遗漏任何需要调整计数的Account(包括旧关联和新关联的)。
  • processUpdate方法仅在Contact的AccountId实际变化时执行操作,避免无效更新。
  • 覆盖三种核心更新场景:
    • Contact从关联A Account改为关联B Account:A减1,B加1。
    • Contact从关联Account改为无关联:原Account减1。
    • Contact从无关联改为关联Account:新Account加1。

内容的提问来源于stack exchange,提问作者Andréa Aline

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 16:05:28