function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Alex McLeanAlex McLean 

How to change a field of an object after inserting another object?

Hi, I am writing a trigger that checks a checkbox field in the contact object after calculating the primaryContact, The primaryContact is the contact who has the most commissions, there is one primary contact per account. My code is able to chose a primary contact but it doesnt seem to update the value of the checkbox to true? This is what I have so far: 
trigger primaryContact on Commision__c (after insert, after update) {
    List<Account> accToCon = [SELECT Id,
                              (SELECT Id, Name, Total_Commission__c FROM Contacts) FROM Account];
    
    for(Commision__c com : Trigger.New){
        for(Account c: accToCon){
            Contact primaryContact;
            if(!c.Contacts.isEmpty()){
                primaryContact = findMaxCommission(c.Contacts);
                System.debug(primaryContact);
                togglePrimaryContact(c.Contacts, primaryContact.id);
            }
            else{
                continue;
            }
        }
    }
    
    Contact findMaxCommission(List<Contact> contacts){ 
        Contact chosenContact = contacts[0];
        Decimal max = contacts[0].Total_Commission__c;
        for (Contact i : contacts) { 
            if (max < i.Total_Commission__c) { 
                max = i.Total_Commission__c; 
                chosenContact = i;
            } 
        } 
        return chosenContact; 
    } 
    
    void togglePrimaryContact(List<Contact> contacts, id primaryContactId){
        for(Contact i : contacts){
            if(i.id == primaryContactId){
                i.Primary__c = true;
            }
            i.Primary__c = false;
        }
    }
}
any help would be greatly appreciated! thanks
 
Bryan Leaman 6Bryan Leaman 6

Alex,

You have several issues here. Primarily, since the trigger is on Commission__c and you're wanting to update the affected Contact records, you need to issue a DML statement on the Contact records that are changing (aka. update(contacts)).

However, you're solution isn't very scaleable -- You're processing ALL accounts and ALL their contacts, even if the commission didn't change.  You should probably get a list of accounts (or contacts) from the Commission object and only query those affected records to begin with.

When changing the primary contact, you should really ensure that you're making a change and NOT issue the update if it's the same contact that was already primary.

NOTE: Untested code. Use/modify at your discression and own the risk:

This example assumes there is an account lookup field on the commission__c object called Account__c. 

I suggest using a map for other records to update like Contact records in this scenario.  This will ensure that you can only list a single Contact once in the list of records to update. It's probably not needed in this example because each contact should only be evaluated as the primary contact 1 time, but it's a handy way to prevent issues.

trigger primaryContact on Commision__c (after insert, after update) {
     
    Set<Id> accountIdSet = new Set<Id>();
    for(Commision__c com : Trigger.New){
        if(com.Account__c!=null) accountIdSet.add(com.Account__c);
    }

    List<Account> accToCon = [SELECT Id,
                              (SELECT Id, Name, Total_Commission__c FROM Contacts) FROM Account
        WHERE Id in :accountIdSet];

   Map<Id,Contact> updateContacts = new Map<Id,Contact>();

    // do not need to loop through commissions again, because we have all affected accounts now
        for(Account c: accToCon){
            Contact oldPrimaryContact;
            Contact newPrimaryContact;
            if(!c.Contacts.isEmpty()){
                oldPrimaryContact = findPrimaryContact(c.Contacts);
                newPrimaryContact = findMaxCommission(c.Contacts);
                System.debug(oldPrimaryContact);
                System.debug(newPrimaryContact);
                // only update contacts if they need to change
                if (oldPrimaryContact!=null && newPrimaryContact!=null && oldPrimaryContact.Id!=newPrimaryContact.Id) {
                    updateContacts.put(oldPrimaryContact.Id oldPrimaryContact);
                }
                if (newPrimaryContact!=null && (oldPrimaryContact==null || oldPrimaryContact.Id!=newPrimaryContact.Id) {
                    updateContacts.put(newPrimaryContact.Id, newPrimaryContact); 
                }
            }
            else{
                continue;
            }
            // need to perform DML to update the contacts
            update(updateContacts.values());
        }
     
    Contact findMaxCommission(List<Contact> contacts){
        Contact chosenContact = contacts[0];
        Decimal max = contacts[0].Total_Commission__c;
        for (Contact i : contacts) {
            if (max < i.Total_Commission__c) {
                max = i.Total_Commission__c;
                chosenContact = i;
            }
        }
        return chosenContact;
    }

    Contact findPrimaryContact(List<Contact> contacts){
        Contact chosenContact;
        for (Contact i : contacts) {
            if (i.Primary__c) {
                chosenContact = i;
            }
        }
        return chosenContact;
    }

    }

}

 
Alex McLeanAlex McLean
Hi Bryan,
Thank you for your quick and extremely informative reply. Your solution makes alot of sense and I can see exactly where I was going wrong and some bad practices that I was applying. Your kindess goes a long way and is very much appreciated. Thank you
Bryan Leaman 6Bryan Leaman 6
Oh, sorry, I see I forgot to actually swap the "Primary Contact" flag. :)