I have a search vfp which is integrated with SAP. I use it for on demand upserting records from SAP into SF Account. Whenever I upsert records in SF, I need a trigger to count the related records from another custom object. Note: I cannot use master detail relationship because records from custom object may not always have related records.

The trigger only fires when the upserted record is updated. How can I make it to fire also upon insert. I tried using after insert but the record is read only.

Triggger Class

Public void triggerAccount(list<account> accountList){
 List<Id> accountId = new List<Id>();
 List<Account> accT = new List<Account>();
 List<Contract__c> A1_contracts= new List<Contract__c>();
 List<Contract__c> A2_contracts= new List<Contract__c>();
 List<Contract__c> A3_contracts= new List<Contract__c>();
 List<Contract__c> A4_contracts= new List<Contract__c>();
 List<Contract__c> A5_contracts= new List<Contract__c>();

 List<Contract__c>Cont_A1_qry = new List<Contract__c>();
 List<Contract__c>Cont_A2_qry = new List<Contract__c>();
 List<Contract__c>Cont_A3_qry = new List<Contract__c>();
 List<Contract__c>Cont_A4_qry = new List<Contract__c>();
 List<Contract__c>Cont_A5_qry = new List<Contract__c>();

    for(Account a: accountList){
    Cont_A1_qry = [Select Id FROM Contract__c WHERE Account__c = : accountId AND Brand__c = 'a1'];
    Cont_A2_qry = [Select Id FROM Contract__c WHERE Account__c = : accountId AND Brand__c = 'a2'];
    Cont_A3_qry = [Select Id FROM Contract__c WHERE Account__c = : accountId AND Brand__c = 'a3'];
    Cont_A4_qry = [Select Id FROM Contract__c WHERE Account__c = : accountId AND Brand__c = 'a4'];
    Cont_A5_qry = [Select Id FROM Contract__c WHERE Account__c = : accountId AND Brand__c = 'a5'];

    for(Account updateAcc : accountList){
        integer iA1 = Cont_A1_qry.size();
        integer iA2 = Cont_A2_qry.size();
        integer iA3 = Cont_A3_qry.size();
        integer iA4 = Cont_A4_qry.size();
        integer iA5 = Cont_A5_qry.size();

        updateAcc.No_of_A1_Contracts__c = iA1 ;
        updateAcc.No_of_A2_Contracts__c = iA2;
        updateAcc.No_of_A3_Contracts__c = iA3;
        updateAcc.No_of_A4_Contracts__c = iA4;
        updateAcc.No_of_A5_Contracts__c = iA5;   


  trigger AccountTrigger on Account (before update) {

        AccountClass acc = new AccountClass();

1 Answer 1


Your trigger looks like it counts the Contract__c objects for various Brand__c values across all of the objects updated and assigns those totals across all of the objects updated. So if for example there are 10 Accounts with 10 'a1' Contracts each, and only one Account is updated No_of_A1_Contracts__c will be set to 10 but if all 10 Accounts are updated No_of_A1_Contracts__c will be set to 100. Not good.

The best way to do this counting is to use an aggregate query something like this (untested one);

for (AggregateResult ar : [
         select Account__c id, Brand__c b, count() c
         from Contract__c
         where Account__c in :accountList
         and Brand__c in ('a1', a2', 'a3', 'a4', 'a5')
         group by Account__c, Brand__c
         ]) {

    Id id = (Id) ar.get('id');
    String b = (String) ar.get('b');
    Integer c = (Integer) ar.get('c');

    Account = accountMap.get(id);
    if (b == 'a1') a.No_of_A1_Contracts__c = c;
    else if (b == 'a2') a.No_of_A2_Contracts__c = c;

I would assume that there would be no Contract__c immediately "after insert" of Account but if you want to count and update there (rather than setting the counts to zero in a "before insert") you could do it like this via new Account instances:

Account[] updates = new Account[] {};
for(Account a : accountList) {
    updates.add(new Account(
            Id = a.Id,
            No_of_A1_Contracts__c = ...,
update updates;

You must log in to answer this question.

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