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
David GreenbergDavid Greenberg 

New to triggers, attempting cross-object update

Good Afternoon,

I am attempting to write an after update trigger that sets the Account status to Active when the Contract is activated.  I am new to Apex triggers.

I tried the following, which does not produce a run-time error, but does not change the value of the field:

trigger setAcctActive on Contract (after update) {

 if (Trigger.isUpdate) {

  for (Contract contract : Trigger.new) {

   if ( contract.Status == 'Activated' ) {

    Account contractAcct = contract.Account;
    contractAcct.AccountStatus__c = 'Active';

   }

  }
 
 }

}

It seems I need to add a commit or something to the code to put the new field value into the database?

Any help?




Divya GoelDivya Goel
use update to update the record.
 
if (Trigger.isUpdate) {

  for (Contract contract : Trigger.new) {

   if ( contract.Status == 'Activated' ) {

    Account contractAcct = contract.Account;
    contractAcct.AccountStatus__c = 'Active';
update contractAcct ;
   }

  }
 
 }

}
Divya Prakash Goel
sdpgoel@yahoo.com
David GreenbergDavid Greenberg
Thanks for the suggestion, Divya.  I thought of that as well.  Unfortunately, it is now throwing a null pointer exception.  Perhaps the syntax is wrong to obtain a reference to the related Account?
SuperfellSuperfell
you need to accumulate a set of accounts to update, then update them, you also need to correctly build the account objects to do the update, related objects are not populated in triggers, so contact.account is always null.

trigger setAcctActive on Contract (after update) {
List ac = new List();
for (Contract contract : Trigger.new) {
if ( contract.Status == 'Activated' ) {
Account a = new Account();
a.Id = contract.accountId;
a.AccountStatus__c = 'Active';
ac.add(a);
}
}
update(ac);
}
David GreenbergDavid Greenberg
Simon to the rescue!  :smileyvery-happy: Thanks!

It's notable that the the accountId is not write-able, so I can't compile:

a.Id = contract.AccountId;

However, the following does work.  I see your assumption about multiple accounts, but doesn't each Contract have only one accountId?

Working version:

trigger setAcctActive on Contract (after update) {

for (Contract contract : Trigger.new) {
if ( contract.Status == 'Activated' ) {
Account a = new Account( Id = contract.AccountId );
//a.Id = contract.accountId;
a.AccountStatus__c = 'Active';
update a;
}
}

}

SuperfellSuperfell
each contract has one account, but each invocation of the trigger can have multiple contracts (e.g., import, api, other apex code, etc).
If you update the accounts one at a time inside the loop you're much more likely to run into the governor limits, your much better off to accumulate the set of accounts to update, and do them in one go.
David GreenbergDavid Greenberg
Excellent, and understood.

Here is the final working code:

trigger setAcctActive on Contract (after update) {

// Create a list of accounts to update
List<Account> acctList = new List<Account>();

for (Contract contract : Trigger.new) {

  // If the contract has been activated...
  if ( contract.Status == 'Activated' ) {

    Account a = new Account( Id = contract.AccountId );
    // ... set the associated Account as active
    a.AccountStatus__c = 'Active';

    acctList.add ( a );

   }
  // update the database with the account status changes
  update acctList;
}
}