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 

Toggling checkbox field by calculating total commissions trigger

Hi, I am trying to create a trigger that will check a primaryContact checbox field on a contact. To do this, I need to calculate who has the most total commissions per account in the system. My approach is th loop thrighn the accounts, then throguh the contacts of each account and caluclate the max total commission then assign the primaryContact checbox to true for this contact and false for all others in the account. This my code so far: 
trigger primaryContact on Commision__c (before insert, before update, before delete) {
    Account acct;
    List<Contact> contacts;
    Map<Id,Account> mapAccount = new Map<Id,Account>([select id from account]);
    Set<ID> accountIds = new Set<ID>();
    accountIds = mapAccount.keySet();
    
    for(Id accountId: accountIds){
        Contact primaryCon;
        getAcctContacts(accountId);
        for(Contact con: contacts){
            System.debug(con);
        }
        if(!contacts.isEmpty()){
            primaryCon = findMaxCommission(contacts);
            togglePrimaryContact(contacts, primaryCon.Id);
            
        }
        else{
            break;
        }
        
        
    }
    
    void getAcctContacts(id id){
        acct = [SELECT Id, Name,
                (SELECT Id, Name, Total_Commission__c FROM Contacts) FROM Account
                where id = :id limit 1];
        contacts = acct.Contacts;
    }
    
    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){
            i.Primary__c = true;
        }
    }
}

This is the error I get
System.DmlException: Insert failed. First exception on row 0; first error: ENTITY_IS_DELETED, entity is deleted: []

I'm not sure what is the best practice for this type of develoment, any help is appreciated.

 
Best Answer chosen by Alex McLean
David Zhu 🔥David Zhu 🔥
1. You want to update contact record when commission object has a change.  It is not the best practice using BEFORE trigger. You will have to change the trigger to After trigger.
trigger primaryContact on Commision__c (AFTER insert, AFTER update, AFTER delete

2.it is not the best practice to query the whole account object on the line
Map<Id,Account> mapAccount = new Map<Id,Account>([select id from account]);
you will come across query 50001 Governor limit error if you have more than 50000 account record.
Use the relationship between commissioned and account or contact to filter the query

3. Method getAcctContacts(id) contains a soql query and this method is used in a loop. Salesforce suggests not put soql in a loop.

All Answers

ShirishaShirisha (Salesforce Developers) 
Hi Alex,

Greetings!

This error occurs when you are trying to refer the delete record and the mapping is incorrect.

I would suggest you to add the debug statements to understand the code execution which will help you in narrow downing the issue.

Kindly let me know if it helps you and close your query by marking it as best answer so that it can help others in the future.

Warm Regards,
Shirisha Pathuri
David Zhu 🔥David Zhu 🔥
1. You want to update contact record when commission object has a change.  It is not the best practice using BEFORE trigger. You will have to change the trigger to After trigger.
trigger primaryContact on Commision__c (AFTER insert, AFTER update, AFTER delete

2.it is not the best practice to query the whole account object on the line
Map<Id,Account> mapAccount = new Map<Id,Account>([select id from account]);
you will come across query 50001 Governor limit error if you have more than 50000 account record.
Use the relationship between commissioned and account or contact to filter the query

3. Method getAcctContacts(id) contains a soql query and this method is used in a loop. Salesforce suggests not put soql in a loop.
This was selected as the best answer
Alex McLeanAlex McLean
Hi, thank you both for a reply. I have gotten the code to run error free but it seems the checbox field is not updating.. here is my refactored code 
trigger primaryContact on Commision__c (before insert, before 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;
        }
    }
}

How can I change it so the primary contact checkbox in contacts is checked? the code is returning the primary contact information correctly.. thank you