4

Need a little help with a trigger. It’s my first, so I’m probably missing something straightforward.

Trying to update a field on Account when a field is updated on a related (master-detail) custom object. I don’t think I can use a Cross-Object workflow here because the field update is part of an Approval Process - so I’m going with a trigger.

When Approval_Stage__c = ‘Approved’ on the custom object I would like corresponding field on Account to read ‘Approved’. If Approval_Stage__c is anything else, the corresponding field on Account should be ‘Not Approved’ (or simply mirror whatever Approval_Stage__c is on the custom object- Pending Approval, Rejected, Submitted for Approval etc.)

The code below only works when Approval_Stage__c == 'Approved' as per the "if" statement - which is expected. I can't however seem to get anything to work when Approval_Stage__c is not equal to "Approved".

Any help would be greatly appreciated.

trigger DealApprovalStatusUpdate on Deal_Approval__c (after Update) {
    //creates a list of all deal approvals that are updated with the associated accountID
    List<ID> approvedAcctIds = new List<ID>();

    for(Deal_Approval__c dealApproval : Trigger.new){
    if (dealApproval.Approval_Stage__c == 'Approved')
    {
       approvedAcctIds.Add(dealapproval.account__r.id);
       } 
 }

    // duplicate the list above and below to hold all non-approved deals ?

   List <Account> approvedAccts = [Select Name, Deal_Approval_Status__c From Account WHERE ID IN: approvedAcctIds];
    for(integer i =0; i < approvedAccts.size(); i++)
    {
        approvedAccts[i].Deal_Approval_Status__c = 'Approved';
     }

    update approvedAccts;
}
1
  • What dotMiko has mentioned, should work but would like to say : if custom object is having master detail relationship with Account- why didn't you use Cross object Workflow field updates. Here I'm not seeing any complex logic which warrants use of Trigger. Jun 10, 2015 at 13:40

4 Answers 4

3

It's not very clear from the other answers to your question but the reason your code is not working is because dealapproval.account__r.id is null. Your SOQL query on Account is not returning any records because of this. You should be doing the following to get the Account Id:

approvedAcctIds.Add(dealapproval.Account__c);

Related objects are not populated in triggers. For example: dealApproval.Approval_Stage__c works but if you reference account fields such as dealapproval.account__r.id they will be null or return a NullPointerException.

Alternative Logic:

If you know the Id of the Account you want to update then you don't need to do a query. You can use the pattern below to directly update the Account without the need for the SOQL statement.

The code below will keep the Account.Deal_Approval_Status__c field insync with the Deal_Approval__c.Approval_Stage__c

trigger DealApprovalStatusUpdate on Deal_Approval__c (after Update) {

    List<Account> accountsToUpdate = new List<Account>();

    for (Deal_Approval__c dealApproval : Trigger.new) {
        Account a = new Account(
                        Id = dealApproval.Account__c,
                        Deal_Approval_Status__c = dealApproval.Approval_Stage__c
                        );
         accountsToUpdate.add(a);
    }
    if (accountsToUpdate.size() > 0) {
        update accountsToUpdate;
    }
}

Or if you wanted the value on Account to be 'Approved' or 'Not Approved' then you can replace this line:

Deal_Approval_Status__c = dealApproval.Approval_Stage__c

with this:

Deal_Approval_Status__c = 
    dealApproval.Approval_Stage__c == 'Approved' 
    ? 'Approved' : 'Not Approved'
1
  • 1
    This worked great. Thanks for the explanation. I wasn't thinking you wanted to use Account a = new Account ( ) - for some reason I thought that only applied if you were inserting a 'new' account...... I tried a few variations on the code in my question and did see a null pointer exception, so really appreciate the insight as to why.
    – jshea
    Jun 11, 2015 at 13:36
1

You can use Process Builder to do this:

Have your Process Builder set on your Child Custom Object. You'll want two different criterias in your Process Builder that fire off your updates.

1) if child object approved = yes, send off record update to account with update to the corresponding status - approved

2) if child object <> approved, send off a record update to account with update to the corresponding status - not approved

Shouldnt need a trigger!

0

you can Use Maps to have easily the matching between accountId and the approvalStatus.

so your code could be something like this:

trigger DealApprovalStatusUpdate on Deal_Approval__c (after Update) {

    Map<Id,String> approvalStatusByAcctIds = new Map<Id,String>();

    for(Deal_Approval__c dealApproval : Trigger.new){
        approvalStatusByAcctIds.put(dealapproval.account__c,dealApproval.Approval_Stage__c);
    }

    // Update accounts
    List <Account> accounts = [Select Name, Deal_Approval_Status__c From Account WHERE ID IN: approvalStatusByAcctIds.keySet()];
    for(integer i =0; i < accounts.size(); i++)
    {
        accounts[i].Deal_Approval_Status__c = approvalStatusByAcctIds.get(accounts[i].Id);
    }

    update accounts;
}
-1

you can simply use this:

    if (dealApproval.Approval_Stage__c == 'Approved')
    {
       dealapproval.Deal_Approval_status__c = 'Approved';
    }
    else
    {
       dealapproval.Deal_Approval_status__c = 'Not Approved';
    }

then update all your dealApprovals accordingly

1
  • Deal_Approval_status__c is a field on Account not Deal_Approval__c
    – BarCotter
    Jun 10, 2015 at 14:46

You must log in to answer this question.

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